summaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java309
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorDevice.java239
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorMode.java458
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtFactory.java121
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtVersion.java17
-rw-r--r--src/newt/classes/com/jogamp/newt/Screen.java157
-rw-r--r--src/newt/classes/com/jogamp/newt/ScreenMode.java208
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java367
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java914
-rw-r--r--[-rwxr-xr-x]src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java131
-rw-r--r--src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java347
-rw-r--r--src/newt/classes/com/jogamp/newt/event/GestureHandler.java143
-rw-r--r--src/newt/classes/com/jogamp/newt/event/InputEvent.java188
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyAdapter.java14
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java1403
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyListener.java36
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MonitorEvent.java73
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java (renamed from src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java)12
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseAdapter.java18
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseEvent.java593
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseListener.java31
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEvent.java148
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java14
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java10
-rw-r--r--src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java12
-rw-r--r--src/newt/classes/com/jogamp/newt/event/OutputEvent.java51
-rw-r--r--src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java228
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java16
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java18
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java17
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowAdapter.java17
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowEvent.java45
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowListener.java28
-rw-r--r--src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java25
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java87
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java54
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java78
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java139
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java888
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java542
-rw-r--r--src/newt/classes/com/jogamp/newt/util/EDTUtil.java99
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MainThread.java96
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorMode.java102
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java258
-rw-r--r--src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java341
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java359
-rw-r--r--[-rwxr-xr-x]src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java (renamed from src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java)171
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java226
-rw-r--r--src/newt/classes/jogamp/newt/Debug.java51
-rw-r--r--src/newt/classes/jogamp/newt/DefaultEDTUtil.java316
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java579
-rw-r--r--src/newt/classes/jogamp/newt/MonitorDeviceImpl.java147
-rw-r--r--src/newt/classes/jogamp/newt/MonitorModeProps.java355
-rw-r--r--src/newt/classes/jogamp/newt/NEWTJNILibLoader.java44
-rw-r--r--src/newt/classes/jogamp/newt/OffscreenWindow.java66
-rw-r--r--src/newt/classes/jogamp/newt/PointerIconImpl.java171
-rw-r--r--src/newt/classes/jogamp/newt/ScreenImpl.java722
-rw-r--r--src/newt/classes/jogamp/newt/ScreenModeStatus.java231
-rw-r--r--src/newt/classes/jogamp/newt/ScreenMonitorState.java195
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java2632
-rw-r--r--src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java16
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java657
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java149
-rw-r--r--src/newt/classes/jogamp/newt/driver/DriverClearFocus.java6
-rw-r--r--src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java12
-rw-r--r--src/newt/classes/jogamp/newt/driver/PNGIcon.java80
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java138
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java408
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java)35
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/MD.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java244
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java103
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java10
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java189
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/WindowDriver.java715
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java409
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java50
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java101
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java285
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java81
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java233
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java)38
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java131
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java329
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java)30
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java118
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java (renamed from src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java)41
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java209
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java115
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java215
-rw-r--r--src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java75
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java)37
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java (renamed from src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java)84
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java (renamed from src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java)47
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java)42
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/KDScreen.java75
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java116
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java (renamed from src/newt/classes/jogamp/newt/driver/kd/KDWindow.java)51
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java959
-rw-r--r--src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java224
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java)87
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java438
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java143
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java432
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java127
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java608
-rw-r--r--src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java89
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java156
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java173
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java (renamed from src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java)262
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java95
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java124
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java (renamed from src/newt/classes/jogamp/newt/driver/x11/X11Display.java)149
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR.java86
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR11.java365
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR13.java274
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java290
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java469
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Screen.java357
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java258
-rw-r--r--src/newt/classes/jogamp/newt/event/NEWTEventTask.java23
-rw-r--r--src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java364
-rw-r--r--src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java375
-rw-r--r--src/newt/native/AndroidWindow.c18
-rw-r--r--src/newt/native/InputEvent.h33
-rw-r--r--src/newt/native/IntelGDL.c24
-rw-r--r--src/newt/native/KDWindow.c53
-rw-r--r--src/newt/native/KeyEvent.h388
-rw-r--r--src/newt/native/MacWindow.m1053
-rw-r--r--src/newt/native/NewtCommon.c116
-rw-r--r--src/newt/native/NewtCommon.h27
-rw-r--r--src/newt/native/NewtMacWindow.h121
-rw-r--r--src/newt/native/NewtMacWindow.m1210
-rw-r--r--src/newt/native/ScreenMode.h15
-rw-r--r--src/newt/native/Window.h17
-rw-r--r--src/newt/native/WindowsWindow.c2294
-rw-r--r--src/newt/native/X11Common.h9
-rw-r--r--src/newt/native/X11Display.c437
-rw-r--r--src/newt/native/X11Event.c305
-rw-r--r--src/newt/native/X11Event.h9
-rw-r--r--src/newt/native/X11RandR11.c371
-rw-r--r--src/newt/native/X11RandR13.c515
-rw-r--r--src/newt/native/X11Screen.c432
-rw-r--r--src/newt/native/X11Screen.h38
-rw-r--r--src/newt/native/X11Window.c402
-rw-r--r--src/newt/native/XCBEvent.c308
-rw-r--r--src/newt/native/XCBEvent.h10
-rw-r--r--src/newt/native/bcm_egl.c (renamed from src/newt/native/BroadcomEGL.c)16
-rw-r--r--src/newt/native/bcm_vc_iv.c463
-rw-r--r--src/newt/native/bcm_vc_iv.h305
150 files changed, 26539 insertions, 10410 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 7b6849a30..4b38fcca5 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -28,21 +28,33 @@
package com.jogamp.newt;
-import com.jogamp.newt.util.EDTUtil;
-import jogamp.newt.Debug;
-
-import java.util.*;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PointImmutable;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.util.EDTUtil;
public abstract class Display {
public static final boolean DEBUG = Debug.debug("Display");
+ protected static final boolean DEBUG_POINTER_ICON = Debug.debug("Display.PointerIcon");
/** return precomputed hashCode from FQN {@link #getFQName()} */
+ @Override
public abstract int hashCode();
/** return true if obj is of type Display and both FQN {@link #getFQName()} equals */
+ @Override
public boolean equals(Object obj) {
if (this == obj) { return true; }
if (obj instanceof Display) {
@@ -53,6 +65,167 @@ public abstract class Display {
}
/**
+ * Native PointerIcon handle.
+ * <p>
+ * Instances can be created via {@link Display}'s
+ * {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(pngResource, ..)}
+ * or {@link Display#createPointerIcon(PixelRectangle, int, int) createPointerIcon(pixelrect, ..)}.
+ * </p>
+ * <p>
+ * Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ * <p>
+ * Instance can be re-validated after destruction via {@link #validate()}.
+ * </p>
+ * <p>
+ * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use!
+ * </p>
+ * <p>
+ * {@link PointerIcon} may be {@link #destroy() destroyed} manually after use,
+ * i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore.
+ * However, this is not required.
+ * </p>
+ * <p>
+ * PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}.
+ * </p>
+ */
+ public static interface PointerIcon extends PixelRectangle {
+ /**
+ * Always neatly packed, i.e. width * bytes_per_pixel.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int getStride();
+
+ /**
+ * Always false, i.e. origin is TOP-LEFT.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ boolean isGLOriented();
+
+ /**
+ * Computes a hash code over:
+ * <ul>
+ * <li>display</li>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * <li>hotspot</li>
+ * </ul>
+ * Dismissing the native handle!
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
+
+ /**
+ * @return the associated Display
+ */
+ Display getDisplay();
+
+ /** Returns the hotspot. */
+ PointImmutable getHotspot();
+
+ /**
+ * Returns true if valid, otherwise false.
+ * <p>
+ * A PointerIcon instance becomes invalid if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ */
+ boolean isValid();
+
+ /**
+ * Returns true if instance {@link #isValid()} or validation was successful, otherwise false.
+ * <p>
+ * Validation, i.e. recreation, is required if instance became invalid, see {@link #isValid()}.
+ * </p>
+ */
+ boolean validate();
+
+ /**
+ * Destroys this instance.
+ * <p>
+ * Will be called automatically if it's {@link #getDisplay() associated Display} is destroyed.
+ * </p>
+ */
+ void destroy();
+ }
+
+ /**
+ * Returns the native platform's {@link PointerIcon.PixelFormat} for pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract PixelFormat getNativePointerIconPixelFormat();
+
+ /**
+ * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract boolean getNativePointerIconForceDirectNIO();
+
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ *
+ * @param pngResource single PNG resource for the {@link PointerIcon}. Only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pngResource is null or invalid
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ * @throws IOException if the <code>pngResource</code> could not be {@link IOUtil.ClassResources#resolve(int) resolved}
+ * or via the PNG parser processing the input stream.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ */
+ public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException;
+
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ * <p>
+ * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()}
+ * is not matched by the given <code>pixelrect</code>, the <code>pixelrect</code> is converted
+ * into the required {@link PixelFormat} and NIO type.
+ * </p>
+ *
+ * @param pixelrect {@link PixelRectangle} source for the {@link PointerIcon}
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pixelrect is null.
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ * @see #getNativePointerIconPixelFormat()
+ * @see #getNativePointerIconForceDirectNIO()
+ */
+ public abstract PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) throws IllegalArgumentException, IllegalStateException;
+
+ /**
* Manual trigger the native creation, if it is not done yet.<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsDevice}, via
* {@link #getGraphicsDevice()}.<br>
@@ -77,7 +250,7 @@ public abstract class Display {
* Stop the running EDT in case this display is destroyed already.<br>
* @return true if EDT has been stopped (destroyed but running), otherwise false.
*/
- public abstract boolean validateEDT();
+ public abstract boolean validateEDTStopped();
/**
* @return true if the native display handle is valid and ready to operate,
@@ -88,7 +261,7 @@ public abstract class Display {
public abstract boolean isNativeValid();
/**
- * @return number of references by Screen
+ * @return number of references
*/
public abstract int getReferenceCount();
@@ -96,7 +269,7 @@ public abstract class Display {
* The 1st call will initiate native creation,
* since we follow the lazy creation pattern.
*
- * @return number of references after adding one
+ * @return number of references post operation
* @throws NativeWindowException if the native creation failed.
* @see #removeReference()
*/
@@ -106,31 +279,37 @@ public abstract class Display {
* The last call may destroy this instance,
* if {@link #getDestroyWhenUnused()} returns <code>true</code>.
*
- * @return number of references after removing one
+ * @return number of references post operation
* @see #addReference()
* @see #getDestroyWhenUnused()
* @see #setDestroyWhenUnused(boolean)
*/
public abstract int removeReference();
+ /**
+ * Return the {@link AbstractGraphicsDevice} used for depending resources lifecycle,
+ * i.e. {@link Screen} and {@link Window}, as well as the event dispatching (EDT). */
public abstract AbstractGraphicsDevice getGraphicsDevice();
/**
- * @return the fully qualified Display name,
- * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}
+ * Return the handle of the {@link AbstractGraphicsDevice} as returned by {@link #getGraphicsDevice()}.
*/
- public abstract String getFQName();
-
public abstract long getHandle();
/**
+ * @return The fully qualified Display name,
+ * which is a key of {@link #getType()} + {@link #getName()} + {@link #getId()}.
+ */
+ public abstract String getFQName();
+
+ /**
* @return this display internal serial id
*/
public abstract int getId();
/**
- * @return This display connection name as defined at creation time.
- * The display connection name is a technical platform specific detail, see {@link AbstractGraphicsDevice#getConnection()}.
+ * @return This display connection name as defined at creation time.
+ * The display connection name is a technical platform specific detail, see {@link AbstractGraphicsDevice#getConnection()}.
*
* @see AbstractGraphicsDevice#getConnection()
*/
@@ -141,36 +320,60 @@ public abstract class Display {
*/
public abstract String getType();
+ /** Return true if this instance is exclusive, i.e. will not be shared. */
+ public abstract boolean isExclusive();
+
+ /**
+ * Sets a new {@link EDTUtil} and returns the previous one.
+ * <p>
+ * If <code>usrEDTUtil</code> is <code>null</code>,
+ * the device's default EDTUtil is created and used.
+ * </p>
+ * <p>
+ * If a previous one exists and it differs from <code>usrEDTUtil</code>,
+ * it's being stopped, wait-until-idle.
+ * </p>
+ * <p>
+ * If <code>usrEDTUtil</code> is not null and equals the previous one,
+ * no change is being made.
+ * </p>
+ */
+ public abstract EDTUtil setEDTUtil(EDTUtil usrEDTUtil);
+
public abstract EDTUtil getEDTUtil();
+ /**
+ * @return true if EDT is running and not subject to be stopped, otherwise false.
+ */
public abstract boolean isEDTRunning();
public abstract void dispatchMessages();
-
+
// Global Displays
- protected static ArrayList<Display> displayList = new ArrayList<Display>();
+ protected static final ArrayList<WeakReference<Display>> displayList = new ArrayList<WeakReference<Display>>();
protected static int displaysActive = 0;
public static void dumpDisplayList(String prefix) {
synchronized(displayList) {
- Iterator<Display> i = displayList.iterator();
System.err.println(prefix+" DisplayList[] entries: "+displayList.size()+" - "+getThreadName());
- for(int j=0; i.hasNext(); j++) {
- Display d = i.next();
- System.err.println(" ["+j+"] : "+d);
+ final Iterator<WeakReference<Display>> ri = displayList.iterator();
+ for(int j=0; ri.hasNext(); j++) {
+ final Display d = ri.next().get();
+ System.err.println(" ["+j+"] : "+d+", GC'ed "+(null==d));
}
}
}
/**
- *
+ *
* @param type
* @param name
- * @param fromIndex start index, then increasing until found or end of list *
- * @return
+ * @param fromIndex start index, then increasing until found or end of list
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
+ * @return
*/
- public static Display getFirstDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, 1);
+ public static Display getFirstDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, 1, shared);
}
/**
@@ -178,33 +381,69 @@ public abstract class Display {
* @param type
* @param name
* @param fromIndex start index, then decreasing until found or end of list. -1 is interpreted as size - 1.
+ * @paran shared if true, only shared instances are found, otherwise also exclusive
* @return
*/
- public static Display getLastDisplayOf(String type, String name, int fromIndex) {
- return getDisplayOfImpl(type, name, fromIndex, -1);
+ public static Display getLastDisplayOf(String type, String name, int fromIndex, boolean shared) {
+ return getDisplayOfImpl(type, name, fromIndex, -1, shared);
}
- private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr) {
+ private static Display getDisplayOfImpl(String type, String name, final int fromIndex, final int incr, boolean shared) {
synchronized(displayList) {
int i = fromIndex >= 0 ? fromIndex : displayList.size() - 1 ;
while( ( incr > 0 ) ? i < displayList.size() : i >= 0 ) {
- Display display = (Display) displayList.get(i);
- if( display.getType().equals(type) &&
- display.getName().equals(name) ) {
- return display;
+ final Display display = displayList.get(i).get();
+ if( null == display ) {
+ // Clear GC'ed dead reference entry!
+ displayList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( display.getType().equals(type) &&
+ display.getName().equals(name) &&
+ ( !shared || shared && !display.isExclusive() )
+ ) {
+ return display;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
+ protected static void addDisplay2List(Display display) {
+ synchronized(displayList) {
+ // GC before add
+ int i=0;
+ while( i < displayList.size() ) {
+ if( null == displayList.get(i).get() ) {
+ displayList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ displayList.add(new WeakReference<Display>(display));
+ }
+ }
+
/** Returns the global display collection */
- @SuppressWarnings("unchecked")
public static Collection<Display> getAllDisplays() {
ArrayList<Display> list;
synchronized(displayList) {
- list = (ArrayList<Display>) displayList.clone();
+ list = new ArrayList<Display>();
+ int i = 0;
+ while( i < displayList.size() ) {
+ final Display d = displayList.get(i).get();
+ if( null == d ) {
+ displayList.remove(i);
+ } else {
+ list.add( displayList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
new file mode 100644
index 000000000..28d9f53a1
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
@@ -0,0 +1,239 @@
+/**
+ * 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 com.jogamp.newt;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import com.jogamp.common.util.ArrayHashSet;
+
+/**
+ * Visual output device, i.e. a CRT, LED ..consisting of it's components:<br>
+ * <ui>
+ * <li>Immutable
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link DimensionImmutable} size in [mm]</li>
+ * <li>{@link MonitorMode} original mode</li>
+ * <li><code>List&lt;MonitorMode&gt;</code> supportedModes</li>
+ * </ul></li>
+ * <li>Mutable
+ * <ul>
+ * <li>{@link MonitorMode} current mode</li>
+ * <li>{@link RectangleImmutable} viewport (rotated)</li>
+ * </ul></li>
+ * </ul>
+ */
+public abstract class MonitorDevice {
+ protected final Screen screen; // backref
+ protected final int nativeId; // unique monitor device ID
+ protected final DimensionImmutable sizeMM; // in [mm]
+ protected final MonitorMode originalMode;
+ protected final ArrayHashSet<MonitorMode> supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly!
+ protected MonitorMode currentMode;
+ protected boolean modeChanged;
+ protected Rectangle viewport;
+
+ protected MonitorDevice(Screen screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) {
+ this.screen = screen;
+ this.nativeId = nativeId;
+ this.sizeMM = sizeMM;
+ this.originalMode = currentMode;
+ this.supportedModes = supportedModes;
+ this.currentMode = currentMode;
+ this.viewport = viewport;
+ this.modeChanged = false;
+ }
+
+ /** Returns the {@link Screen} owning this monitor. */
+ public final Screen getScreen() {
+ return screen;
+ }
+
+ /**
+ * Tests equality of two <code>MonitorDevice</code> objects
+ * by evaluating equality of it's components:<br>
+ * <ul>
+ * <li><code>nativeID</code></li>
+ * </ul>
+ * <br>
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof MonitorDevice) {
+ MonitorDevice md = (MonitorDevice)obj;
+ return md.nativeId == nativeId;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br>
+ * <ul>
+ * <li><code>nativeID</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return nativeId;
+ }
+
+ /** @return the immutable unique native Id of this monitor device. */
+ public final int getId() { return nativeId; }
+
+ /**
+ * @return the immutable monitor size in millimeters.
+ */
+ public final DimensionImmutable getSizeMM() {
+ return sizeMM;
+ }
+
+ /**
+ * Returns the immutable original {@link com.jogamp.newt.MonitorMode}, as used at NEWT initialization.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ */
+ public final MonitorMode getOriginalMode() {
+ return originalMode;
+ }
+
+ /**
+ * Returns a list of immutable {@link MonitorMode}s supported by this monitor.
+ * <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
+ * <p>
+ * Use w/ care, it's not a copy!
+ * </p>
+ */
+ public final List<MonitorMode> getSupportedModes() {
+ return supportedModes.getData();
+ }
+
+ /** Returns the {@link RectangleImmutable rectangular} portion of the rotated virtual {@link Screen} size represented by this monitor. */
+ public final RectangleImmutable getViewport() {
+ return viewport;
+ }
+
+ /** Returns <code>true</code> if given coordinates are contained by this {@link #getViewport() viewport}, otherwise <code>false</code>. */
+ public final boolean contains(int x, int y) {
+ return x >= viewport.getX() &&
+ x < viewport.getX() + viewport.getWidth() &&
+ y >= viewport.getY() &&
+ y < viewport.getY() + viewport.getHeight() ;
+ }
+
+ /**
+ * Returns the coverage of given rectangle w/ this this {@link #getViewport() viewport}, i.e. between <code>0.0</code> and <code>1.0</code>.
+ * <p>
+ * Coverage is computed by:
+ * <pre>
+ * isect = viewport.intersection(r);
+ * coverage = area( isect ) / area( viewport ) ;
+ * </pre>
+ * </p>
+ */
+ public final float coverage(RectangleImmutable r) {
+ return viewport.coverage(r);
+ }
+
+ /**
+ * Returns the union of the given monitor's {@link #getViewport() viewport}.
+ * @param result storage for result, will be returned
+ * @param monitors given list of monitors
+ * @return viewport representing the union of given monitor's viewport.
+ */
+ public static Rectangle unionOfViewports(final Rectangle result, final List<MonitorDevice> monitors) {
+ int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE;
+ int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE;
+ for(int i=monitors.size()-1; i>=0; i--) {
+ final RectangleImmutable vp = monitors.get(i).getViewport();
+ x1 = Math.min(x1, vp.getX());
+ x2 = Math.max(x2, vp.getX() + vp.getWidth());
+ y1 = Math.min(y1, vp.getY());
+ y2 = Math.max(y2, vp.getY() + vp.getHeight());
+ }
+ result.set(x1, y1, x2 - x1, y2 - y1);
+ return result;
+ }
+
+ public final boolean isOriginalMode() {
+ return currentMode.hashCode() == originalMode.hashCode();
+ }
+
+ /**
+ * Returns <code>true</true> if the {@link MonitorMode}
+ * has been changed programmatic via this API <i>only</i>, otherwise <code>false</code>.
+ * <p>
+ * Note: We cannot guarantee that we won't interfere w/ another running
+ * application's screen mode change or vice versa.
+ * </p>
+ */
+ public final boolean isModeChangedByUs() {
+ return modeChanged && !isOriginalMode();
+ }
+
+ /**
+ * Returns the cached current {@link MonitorMode} w/o native query.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ */
+ public final MonitorMode getCurrentMode() {
+ return currentMode;
+ }
+
+ /**
+ * Returns the current {@link MonitorMode} resulting from a native query.
+ * <p>
+ * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * </p>
+ */
+ public abstract MonitorMode queryCurrentMode();
+
+ /**
+ * Set the current {@link com.jogamp.newt.MonitorMode}.
+ * @param mode to be made current, must be element of the list {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}.
+ * @return true if successful, otherwise false
+ */
+ public abstract boolean setCurrentMode(MonitorMode mode);
+
+ @Override
+ public String toString() {
+ return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewport+ ", orig "+originalMode+", curr "+currentMode+
+ ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]";
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/MonitorMode.java b/src/newt/classes/com/jogamp/newt/MonitorMode.java
new file mode 100644
index 000000000..9690f18db
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/MonitorMode.java
@@ -0,0 +1,458 @@
+/**
+ * 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 com.jogamp.newt;
+
+import java.util.Comparator;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import com.jogamp.newt.util.MonitorModeUtil;
+
+
+/**
+ * Immutable MonitorMode Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link SizeAndRRate}, consist out of non rotated {@link #getSurfaceSize() surface size}, {@link #getRefreshRate() refresh rate} and {@link #getFlags() flags}.</li>
+ * <li><code>rotation</code>, measured counter clockwise (CCW)</li>
+ * </ul>
+ *
+ * <i>Aquire and filter MonitorMode</i><br>
+ * <ul>
+ * <li>{@link MonitorDevice} Selection:
+ * <ul>
+ * <li>A List of all {@link MonitorDevice}s is accessible via {@link Screen#getMonitorDevices()}.</li>
+ * <li>The main monitor used by a windows is accessible via {@link Window#getMainMonitor()}.</li>
+ * <li>The main monitor covering an arbitrary rectnagle is accessible via {@link Screen#getMainMonitor(RectangleImmutable)}.</li>
+ * </ul></li>
+ * <li>The current MonitorMode can be obtained via {@link MonitorDevice#getCurrentMode()}.</li>
+ * <li>The original MonitorMode can be obtained via {@link MonitorDevice#getOriginalMode()}.</li>
+ * <li>{@link MonitorMode} Filtering:
+ * <ul>
+ * <li>A {@link MonitorDevice}'s MonitorModes is accessible via {@link MonitorDevice#getSupportedModes()}.</li>
+ * <li>You may utilize {@link MonitorModeUtil} to filter and select a desired MonitorMode.</li>
+ * </ul></li>
+ * </ul>
+ * <br>
+ *
+ * <i>Changing MonitorMode</i><br>
+ * <ul>
+ * <li> Use {@link MonitorDevice#setCurrentMode(MonitorMode)}
+ * to change the current MonitorMode for all {@link Screen}s referenced via the {@link Screen#getFQName() full qualified name (FQN)}.</li>
+ * <li> The {@link MonitorDevice#getOriginalMode() original mode} is restored when
+ * <ul>
+ * <li>the last FQN referenced Screen closes.</li>
+ * <li>the JVM shuts down.</li>
+ * </ul></li>
+ * </ul>
+ * <br>
+ * Example for changing the MonitorMode:
+ * <pre>
+ // Pick the monitor:
+ // Either the one used by a window ..
+ MonitorDevice monitor = window.getMainMonitor();
+
+ // Or arbitrary from the list ..
+ List<MonitorDevice> allMonitor = getMonitorDevices();
+ MonitorDevice monitor = allMonitor.get(0);
+
+ // Current and original modes ..
+ MonitorMode mmCurrent = monitor.queryCurrentMode();
+ MonitorMode mmOrig = monitor.getOriginalMode();
+
+ // Target resolution
+ Dimension res = new Dimension(800, 600);
+
+ // Target refresh rate shall be similar to current one ..
+ float freq = mmCurrent.getRefreshRate();
+
+ // Target rotation shall be similar to current one
+ int rot = mmCurrent.getRotation();
+
+ // Filter criterias sequential out of all available MonitorMode of the chosen MonitorDevice
+ List<MonitorMode> monitorModes = monitor.getSupportedModes();
+ monitorModes = MonitorModeUtil.filterByFlags(monitorModes, 0); // no interlace, double-scan etc
+ monitorModes = MonitorModeUtil.filterByRotation(monitorModes, rot);
+ monitorModes = MonitorModeUtil.filterByResolution(monitorModes, res);
+ monitorModes = MonitorModeUtil.filterByRate(monitorModes, freq);
+ monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes);
+
+ // pick 1st one and set to current ..
+ MonitorMode mm = monitorModes.get(0);
+ monitor.setCurrentMode(mm);
+ * </pre>
+ */
+public class MonitorMode implements Comparable<MonitorMode> {
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the ascending order. */
+ public static final Comparator<MonitorMode> monitorModeComparator = new Comparator<MonitorMode>() {
+ @Override
+ public int compare(MonitorMode mm1, MonitorMode mm2) {
+ return mm1.compareTo(mm2);
+ } };
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the descending order. */
+ public static final Comparator<MonitorMode> monitorModeComparatorInv = new Comparator<MonitorMode>() {
+ @Override
+ public int compare(MonitorMode mm1, MonitorMode mm2) {
+ return mm2.compareTo(mm1);
+ } };
+
+ /**
+ * Immutable <i>surfaceSize, flags and refreshRate</i> Class, consisting of it's read only components:<br>
+ * <ul>
+ * <li>nativeId</li>
+ * <li>{@link SurfaceSize} surface memory size</li>
+ * <li><code>flags</code></li>
+ * <li><code>refresh rate</code></li>
+ * </ul>
+ */
+ public static class SizeAndRRate implements Comparable<SizeAndRRate> {
+ /** Non rotated surface size */
+ public final SurfaceSize surfaceSize;
+ /** Mode bitfield flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+ public final int flags;
+ /** Vertical refresh rate */
+ public final float refreshRate;
+ public final int hashCode;
+
+ public SizeAndRRate(SurfaceSize surfaceSize, float refreshRate, int flags) {
+ if(null==surfaceSize) {
+ throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
+ }
+ this.surfaceSize=surfaceSize;
+ this.flags = flags;
+ this.refreshRate=refreshRate;
+ this.hashCode = getHashCode();
+ }
+
+ private final static String STR_INTERLACE = "Interlace";
+ private final static String STR_DOUBLESCAN = "DoubleScan";
+ private final static String STR_SEP = ", ";
+
+ public static final StringBuilder flags2String(int flags) {
+ final StringBuilder sb = new StringBuilder();
+ boolean sp = false;
+ if( 0 != ( flags & FLAG_INTERLACE ) ) {
+ sb.append(STR_INTERLACE);
+ sp = true;
+ }
+ if( 0 != ( flags & FLAG_DOUBLESCAN ) ) {
+ if( sp ) {
+ sb.append(STR_SEP);
+ }
+ sb.append(STR_DOUBLESCAN);
+ sp = true;
+ }
+ return sb;
+ }
+ @Override
+ public final String toString() {
+ return surfaceSize+" @ "+refreshRate+" Hz, flags ["+flags2String(flags).toString()+"]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link SurfaceSize#compareTo(SurfaceSize) surfaceSize} 1st, then {@link #flags}, then {@link #refreshRate}.
+ * </p>
+ * <p>
+ * Flags are compared as follows:
+ * <pre>
+ * NONE > DOUBLESCAN > INTERLACE
+ * </pre>
+ * </p>
+ * <p>
+ * Refresh rate differences of &lt; 0.01 are considered equal (epsilon).
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final SizeAndRRate sszr) {
+ final int rssz = surfaceSize.compareTo(sszr.surfaceSize);
+ if( 0 != rssz ) {
+ return rssz;
+ }
+ final int tflags = 0 == flags ? Integer.MAX_VALUE : flags; // normalize NONE
+ final int xflags = 0 == sszr.flags ? Integer.MAX_VALUE : sszr.flags; // normalize NONE
+ if( tflags == xflags ) {
+ final float refreshEpsilon = 0.01f; // reasonable sorting granularity of refresh rate
+ final float drate = refreshRate - sszr.refreshRate;
+ if( Math.abs(drate) < refreshEpsilon ) {
+ return 0;
+ } else if( drate > refreshEpsilon ) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ if(tflags > xflags) {
+ return 1;
+ } else if(tflags < xflags) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ /**
+ * Tests equality of two {@link SizeAndRRate} objects
+ * by evaluating equality of it's components:<br/>
+ * <ul>
+ * <li><code>surfaceSize</code></li>
+ * <li><code>refreshRate</code></li>
+ * <li><code>flags</code></li>
+ * </ul>
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof SizeAndRRate) {
+ final SizeAndRRate p = (SizeAndRRate)obj;
+ return surfaceSize.equals(p.surfaceSize) &&
+ flags == p.flags &&
+ refreshRate == p.refreshRate ;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br/>
+ * <ul>
+ * <li><code>surfaceSize</code></li>
+ * <li><code>flags</code></li>
+ * <li><code>refreshRate</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return hashCode;
+ }
+ private final int getHashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + surfaceSize.hashCode();
+ hash = ((hash << 5) - hash) + flags;
+ hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f);
+ return hash;
+ }
+ }
+
+ /** zero rotation, compared to normal settings */
+ public static final int ROTATE_0 = 0;
+
+ /** 90 degrees CCW rotation */
+ public static final int ROTATE_90 = 90;
+
+ /** 180 degrees CCW rotation */
+ public static final int ROTATE_180 = 180;
+
+ /** 270 degrees CCW rotation */
+ public static final int ROTATE_270 = 270;
+
+ /** Frame is split into two fields. See {@link #getFlags()}. */
+ public static final int FLAG_INTERLACE = 1 << 0;
+
+ /** Lines are doubled. See {@link #getFlags()}. */
+ public static final int FLAG_DOUBLESCAN = 1 << 1;
+
+ /** The immutable native Id of this instance, which may not be unique. */
+ private final int nativeId;
+ private final SizeAndRRate sizeAndRRate;
+ private final int rotation;
+ private final int hashCode;
+
+ public static boolean isRotationValid(int rotation) {
+ return rotation == MonitorMode.ROTATE_0 || rotation == MonitorMode.ROTATE_90 ||
+ rotation == MonitorMode.ROTATE_180 || rotation == MonitorMode.ROTATE_270 ;
+ }
+
+ /**
+ * @param sizeAndRRate the surface size and refresh rate mode
+ * @param rotation the screen rotation, measured counter clockwise (CCW)
+ */
+ public MonitorMode(int nativeId, SizeAndRRate sizeAndRRate, int rotation) {
+ if ( !isRotationValid(rotation) ) {
+ throw new RuntimeException("invalid rotation: "+rotation);
+ }
+ this.nativeId = nativeId;
+ this.sizeAndRRate = sizeAndRRate;
+ this.rotation = rotation;
+ this.hashCode = getHashCode();
+ }
+
+ /**
+ * Creates a user instance w/o {@link #getId() identity} to filter our matching modes w/ identity.
+ * <p>
+ * See {@link com.jogamp.newt.util.MonitorModeUtil} for filter utilities.
+ * </p>
+ * @param surfaceSize
+ * @param refreshRate
+ * @param flags
+ * @param rotation
+ */
+ public MonitorMode(SurfaceSize surfaceSize, float refreshRate, int flags, int rotation) {
+ this(0, new SizeAndRRate(surfaceSize, refreshRate, flags), rotation);
+ }
+
+ /** @return the immutable native Id of this mode, may not be unique, may be 0. */
+ public final int getId() { return nativeId; }
+
+ /** Returns the <i>surfaceSize and refreshRate</i> instance. */
+ public final SizeAndRRate getSizeAndRRate() {
+ return sizeAndRRate;
+ }
+
+ /** Returns the unrotated {@link SurfaceSize} */
+ public final SurfaceSize getSurfaceSize() {
+ return sizeAndRRate.surfaceSize;
+ }
+
+ /** Returns the vertical refresh rate. */
+ public final float getRefreshRate() {
+ return sizeAndRRate.refreshRate;
+ }
+
+ /** Returns bitfield w/ flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
+ public final int getFlags() {
+ return sizeAndRRate.flags;
+ }
+
+ /** Returns the CCW rotation of this mode */
+ public final int getRotation() {
+ return rotation;
+ }
+
+ /** Returns the rotated screen width,
+ * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+ * and <code>getRotation()</code>
+ */
+ public final int getRotatedWidth() {
+ return getRotatedWH(true);
+ }
+
+ /** Returns the rotated screen height,
+ * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
+ * and <code>getRotation()</code>
+ */
+ public final int getRotatedHeight() {
+ return getRotatedWH(false);
+ }
+
+ @Override
+ public final String toString() {
+ return "[Id "+Display.toHexString(nativeId)+", " + sizeAndRRate + ", " + rotation + " degr]";
+ }
+
+ /**
+ * <p>
+ * Compares {@link SizeAndRRate#compareTo(SizeAndRRate) sizeAndRRate} 1st, then {@link #rotation}.
+ * </p>
+ * <p>
+ * Rotation is compared inverted, i.e. <code>360 - rotation</code>,
+ * so the lowest rotation reflects a higher value.
+ * </p>
+ * <p>
+ * Order of comparing MonitorMode:
+ * <ul>
+ * <li>resolution</li>
+ * <li>bits per pixel</li>
+ * <li>flags</li>
+ * <li>refresh rate</li>
+ * <li>rotation</li>
+ * </ul>
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final MonitorMode mm) {
+ final int c = sizeAndRRate.compareTo(mm.sizeAndRRate);
+ if( 0 != c ) {
+ return c;
+ }
+ final int trot = 360 - rotation; // normalize rotation
+ final int xrot = 360 - mm.rotation; // normalize rotation
+ if(trot > xrot) {
+ return 1;
+ } else if(trot < xrot) {
+ return -1;
+ }
+ return 0;
+ }
+
+ /**
+ * Tests equality of two {@link MonitorMode} objects
+ * by evaluating equality of it's components:<br/>
+ * <ul>
+ * <li><code>nativeId</code></li>
+ * <li><code>sizeAndRRate</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) { return true; }
+ if (obj instanceof MonitorMode) {
+ MonitorMode sm = (MonitorMode)obj;
+ return sm.nativeId == this.nativeId &&
+ sm.sizeAndRRate.equals(sizeAndRRate) &&
+ sm.rotation == this.rotation ;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a combined hash code of it's elements:<br/>
+ * <ul>
+ * <li><code>nativeId</code></li>
+ * <li><code>sizeAndRRate</code></li>
+ * <li><code>rotation</code></li>
+ * </ul>
+ */
+ @Override
+ public final int hashCode() {
+ return hashCode;
+ }
+ private final int getHashCode() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + getId();
+ hash = ((hash << 5) - hash) + sizeAndRRate.hashCode();
+ hash = ((hash << 5) - hash) + getRotation();
+ return hash;
+ }
+
+ private final int getRotatedWH(boolean width) {
+ final DimensionImmutable d = sizeAndRRate.surfaceSize.getResolution();
+ final boolean swap = MonitorMode.ROTATE_90 == rotation || MonitorMode.ROTATE_270 == rotation ;
+ if ( ( width && swap ) || ( !width && !swap ) ) {
+ return d.getHeight();
+ }
+ return d.getWidth();
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index 61dbfb34c..9685200eb 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,15 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -41,6 +45,8 @@ import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowFactory;
+import com.jogamp.common.util.IOUtil;
+
import jogamp.newt.Debug;
import jogamp.newt.DisplayImpl;
import jogamp.newt.ScreenImpl;
@@ -49,17 +55,57 @@ import jogamp.newt.WindowImpl;
public class NewtFactory {
public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window");
- // Work-around for initialization order problems on Mac OS X
- // between native Newt and (apparently) Fmod
+ public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver";
+
+ private static IOUtil.ClassResources defaultWindowIcons;
+
static {
- NativeWindowFactory.initSingleton(false); // last resort ..
- WindowImpl.init(NativeWindowFactory.getNativeWindowType(true));
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ NativeWindowFactory.initSingleton(); // last resort ..
+ {
+ /** See API Doc in {@link Window} ! */
+ final String[] paths = Debug.getProperty("newt.window.icons", true, "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png").split("\\s");
+ if( paths.length < 2 ) {
+ throw new IllegalArgumentException("Property 'newt.window.icons' did not specify at least two PNG icons, but "+Arrays.toString(paths));
+ }
+ final Class<?> clazz = NewtFactory.class;
+ defaultWindowIcons = new IOUtil.ClassResources(clazz, paths);
+ }
+ return null;
+ } } );
}
+ /**
+ * Returns the application window icon resources to be used.
+ * <p>
+ * Property <code>newt.window.icons</code> may define a list of PNG icons separated by a whitespace character.
+ * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution.
+ * </p>
+ * <p>
+ * Users may also specify application window icons using {@link #setWindowIcons(com.jogamp.common.util.IOUtil.ClassResources)}.
+ * </p>
+ */
+ public static IOUtil.ClassResources getWindowIcons() { return defaultWindowIcons; }
+
+ /**
+ * Allow user to set custom window icons, only applicable at application start before creating any NEWT instance.
+ * <p>
+ * Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution.
+ * </p>
+ */
+ public static void setWindowIcons(IOUtil.ClassResources cres) { defaultWindowIcons = cres; }
+
public static Class<?> getCustomClass(String packageName, String classBaseName) {
Class<?> clazz = null;
if(packageName!=null && classBaseName!=null) {
- final String clazzName = packageName + "." + classBaseName ;
+ final String clazzName;
+ if( packageName.startsWith(".") ) {
+ clazzName = DRIVER_DEFAULT_ROOT_PACKAGE + packageName + "." + classBaseName ;
+ } else {
+ clazzName = packageName + "." + classBaseName ;
+ }
try {
clazz = Class.forName(clazzName);
} catch (Throwable t) {
@@ -74,7 +120,7 @@ public class NewtFactory {
private static boolean useEDT = true;
- /**
+ /**
* Toggles the usage of an EventDispatchThread while creating a Display.<br>
* The default is enabled.<br>
* The EventDispatchThread is thread local to the Display instance.<br>
@@ -92,7 +138,7 @@ public class NewtFactory {
* Native creation is lazily done at usage, ie. {@link Display#addReference()}.
* </p>
* <p>
- * An already existing display connection of the same <code>name</code> will be reused.
+ * An already existing display connection of the same <code>name</code> will be reused.
* </p>
* @param name the display connection name which is a technical platform specific detail,
* see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default.
@@ -198,7 +244,7 @@ public class NewtFactory {
* </p>
*/
public static Window createWindow(Screen screen, CapabilitiesImmutable caps) {
- return createWindowImpl(screen, caps);
+ return WindowImpl.create(null, 0, screen, caps);
}
/**
@@ -225,6 +271,9 @@ public class NewtFactory {
*/
public static Window createWindow(NativeWindow parentWindow, CapabilitiesImmutable caps) {
final String type = NativeWindowFactory.getNativeWindowType(true);
+ if( null == parentWindow ) {
+ return createWindowImpl(type, caps);
+ }
Screen screen = null;
Window newtParentWindow = null;
@@ -245,7 +294,7 @@ public class NewtFactory {
screen = NewtFactory.createScreen(display, 0); // screen 0
}
}
- final Window win = createWindowImpl(parentWindow, screen, caps);
+ final Window win = WindowImpl.create(parentWindow, 0, screen, caps);
win.setSize(parentWindow.getWidth(), parentWindow.getHeight());
if ( null != newtParentWindow ) {
@@ -255,19 +304,7 @@ public class NewtFactory {
return win;
}
- protected static Window createWindowImpl(NativeWindow parentNativeWindow, Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(parentNativeWindow, 0, screen, caps);
- }
-
- protected static Window createWindowImpl(long parentWindowHandle, Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(null, parentWindowHandle, screen, caps);
- }
-
- protected static Window createWindowImpl(Screen screen, CapabilitiesImmutable caps) {
- return WindowImpl.create(null, 0, screen, caps);
- }
-
- protected static Window createWindowImpl(String type, CapabilitiesImmutable caps) {
+ private static Window createWindowImpl(String type, CapabilitiesImmutable caps) {
Display display = NewtFactory.createDisplay(type, null, true); // local display
Screen screen = NewtFactory.createScreen(display, 0); // screen 0
return WindowImpl.create(null, 0, screen, caps);
@@ -276,11 +313,17 @@ public class NewtFactory {
/**
* Create a child Window entity attached to the given parent, incl native creation<br>
*
- * @param parentWindowObject the native parent window handle
- * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always
+ * @param displayConnection the parent window's display connection
+ * @param screenIdx the desired screen index
+ * @param parentWindowHandle the native parent window handle
+ * @param caps the desired capabilities
+ * @return
*/
- public static Window createWindow(long parentWindowHandle, Screen screen, CapabilitiesImmutable caps) {
- return createWindowImpl(parentWindowHandle, screen, caps);
+ public static Window createWindow(String displayConnection, int screenIdx, long parentWindowHandle, CapabilitiesImmutable caps) {
+ final String type = NativeWindowFactory.getNativeWindowType(true);
+ Display display = NewtFactory.createDisplay(type, displayConnection, true);
+ Screen screen = NewtFactory.createScreen(display, screenIdx);
+ return WindowImpl.create(null, parentWindowHandle, screen, caps);
}
/**
@@ -298,14 +341,14 @@ public class NewtFactory {
* Instantiate a Display entity using the native handle.
*/
public static Display createDisplay(String type, long handle, boolean reuse) {
- return DisplayImpl.create(type, null, handle, false);
+ return DisplayImpl.create(type, null, handle, reuse);
}
public static boolean isScreenCompatible(NativeWindow parent, Screen childScreen) {
// Get parent's NativeWindow details
- AbstractGraphicsConfiguration parentConfig = (AbstractGraphicsConfiguration) parent.getGraphicsConfiguration();
- AbstractGraphicsScreen parentScreen = (AbstractGraphicsScreen) parentConfig.getScreen();
- AbstractGraphicsDevice parentDevice = (AbstractGraphicsDevice) parentScreen.getDevice();
+ AbstractGraphicsConfiguration parentConfig = parent.getGraphicsConfiguration();
+ AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
+ AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
DisplayImpl childDisplay = (DisplayImpl) childScreen.getDisplay();
String parentDisplayName = childDisplay.validateDisplayName(null, parentDevice.getHandle());
@@ -326,9 +369,9 @@ public class NewtFactory {
public static Screen createCompatibleScreen(NativeWindow parent, Screen childScreen) {
// Get parent's NativeWindow details
- AbstractGraphicsConfiguration parentConfig = (AbstractGraphicsConfiguration) parent.getGraphicsConfiguration();
- AbstractGraphicsScreen parentScreen = (AbstractGraphicsScreen) parentConfig.getScreen();
- AbstractGraphicsDevice parentDevice = (AbstractGraphicsDevice) parentScreen.getDevice();
+ AbstractGraphicsConfiguration parentConfig = parent.getGraphicsConfiguration();
+ AbstractGraphicsScreen parentScreen = parentConfig.getScreen();
+ AbstractGraphicsDevice parentDevice = parentScreen.getDevice();
if(null != childScreen) {
// check if child Display/Screen is compatible already
diff --git a/src/newt/classes/com/jogamp/newt/NewtVersion.java b/src/newt/classes/com/jogamp/newt/NewtVersion.java
index 961ffdf6a..e70d63f88 100644
--- a/src/newt/classes/com/jogamp/newt/NewtVersion.java
+++ b/src/newt/classes/com/jogamp/newt/NewtVersion.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt;
import com.jogamp.common.GlueGenVersion;
@@ -46,9 +46,10 @@ public class NewtVersion extends JogampVersion {
if(null == jogampCommonVersionInfo) { // volatile: ok
synchronized(NewtVersion.class) {
if( null == jogampCommonVersionInfo ) {
- final String packageName = "com.jogamp.newt";
- final Manifest mf = VersionUtil.getManifest(NewtVersion.class.getClassLoader(), packageName);
- jogampCommonVersionInfo = new NewtVersion(packageName, mf);
+ final String packageName1 = "com.jogamp.newt"; // atomic packaging - and identity
+ final String packageName2 = "javax.media.opengl"; // all packaging
+ final Manifest mf = VersionUtil.getManifest(NativeWindowVersion.class.getClassLoader(), new String[]{ packageName1, packageName2 } );
+ jogampCommonVersionInfo = new NewtVersion(packageName1, mf);
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index 26f19ad6b..ef62ec95d 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -27,14 +27,21 @@
*/
package com.jogamp.newt;
-import com.jogamp.newt.event.ScreenModeListener;
+import com.jogamp.newt.event.MonitorModeListener;
import jogamp.newt.Debug;
+
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+/**
+ * A screen may span multiple {@link MonitorDevice}s representing their combined virtual size.
+ */
public abstract class Screen {
/**
@@ -46,9 +53,11 @@ public abstract class Screen {
public static final boolean DEBUG = Debug.debug("Screen");
/** return precomputed hashCode from FQN {@link #getFQName()} */
+ @Override
public abstract int hashCode();
/** return true if obj is of type Display and both FQN {@link #getFQName()} equals */
+ @Override
public boolean equals(Object obj) {
if (this == obj) { return true; }
if (obj instanceof Screen) {
@@ -59,7 +68,7 @@ public abstract class Screen {
}
/**
- * Manual trigger the native creation, if it is not done yet..<br>
+ * Manual trigger the native creation, if not done yet..<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsScreen}, via
* {@link #getGraphicsScreen()}.<br>
* Otherwise the abstract device won't be available before the dependent component (Window) is realized.
@@ -89,13 +98,14 @@ public abstract class Screen {
public abstract boolean isNativeValid();
/**
- * @return number of references by Window
+ * @return number of references
*/
public abstract int getReferenceCount();
/**
* See {@link Display#addReference()}
*
+ * @return number of references post operation
* @throws NativeWindowException if the native creation failed.
* @see #removeReference()
* @see #setDestroyWhenUnused(boolean)
@@ -106,6 +116,7 @@ public abstract class Screen {
/**
* See {@link Display#removeReference()}
*
+ * @return number of references post operation
* @see #addReference()
* @see #setDestroyWhenUnused(boolean)
* @see #getDestroyWhenUnused()
@@ -120,81 +131,104 @@ public abstract class Screen {
public abstract int getIndex();
/**
- * @return the x position of the virtual top-left origin.
+ * @return the x position of the virtual viewport's top-left origin.
*/
public abstract int getX();
-
+
/**
- * @return the y position of the virtual top-left origin.
+ * @return the y position of the virtual viewport's top-left origin.
*/
public abstract int getY();
-
+
/**
- * @return the <b>rotated</b> virtual width.
+ * @return the <b>rotated</b> virtual viewport's width.
*/
public abstract int getWidth();
/**
- * @return the <b>rotated</b> virtual height.
+ * @return the <b>rotated</b> virtual viewport's height.
*/
public abstract int getHeight();
/**
+ * @return the <b>rotated</b> virtual viewport, i.e. origin and size.
+ */
+ public abstract RectangleImmutable getViewport();
+
+ /**
* @return the associated Display
*/
public abstract Display getDisplay();
- /**
- * @return the screen fully qualified Screen name,
+ /**
+ * @return The screen fully qualified Screen name,
* which is a key of {@link com.jogamp.newt.Display#getFQName()} + {@link #getIndex()}.
*/
public abstract String getFQName();
/**
- * @param sml ScreenModeListener to be added for ScreenMode change events
+ * Return a list of all {@link MonitorMode}s for all {@link MonitorDevice}s.
+ * <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
*/
- public abstract void addScreenModeListener(ScreenModeListener sml);
+ public abstract List<MonitorMode> getMonitorModes();
/**
- * @param sml ScreenModeListener to be removed from ScreenMode change events
+ * Return a list of available {@link MonitorDevice}s.
*/
- public abstract void removeScreenModeListener(ScreenModeListener sml);
+ public abstract List<MonitorDevice> getMonitorDevices();
- /**
- * Return a list of available {@link com.jogamp.newt.ScreenMode ScreenMode}s.
+ /**
+ * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport}
+ * {@link MonitorDevice#coverage(RectangleImmutable) covers} the given rectangle the most.
* <p>
- * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this
- * native type {@link com.jogamp.newt.Display#getType()}, it returns a list of size one with the current screen size.</p>
- *
- * @return a shallow copy of the internal immutable {@link com.jogamp.newt.ScreenMode ScreenMode}s.
+ * If no coverage is detected the first {@link MonitorDevice} is returned.
+ * </p>
*/
- public abstract List<ScreenMode> getScreenModes();
+ public final MonitorDevice getMainMonitor(RectangleImmutable r) {
+ MonitorDevice res = null;
+ float maxCoverage = Float.MIN_VALUE;
+ final List<MonitorDevice> monitors = getMonitorDevices();
+ for(int i=monitors.size()-1; i>=0; i--) {
+ final MonitorDevice monitor = monitors.get(i);
+ final float coverage = monitor.coverage(r);
+ if( coverage > maxCoverage ) {
+ maxCoverage = coverage;
+ res = monitor;
+ }
+ }
+ if( maxCoverage > 0.0f && null != res ) {
+ return res;
+ }
+ return monitors.get(0);
+ }
/**
- * Return the original {@link com.jogamp.newt.ScreenMode}, as used at NEWT initialization.
- * @return original ScreenMode which is element of the list {@link #getScreenModes()}.
+ * Returns the union of all monitor's {@link MonitorDevice#getViewport() viewport}.
+ * <p>
+ * Should be equal to {@link #getX()}, {@link #getY()}, {@link #getWidth()} and {@link #getHeight()},
+ * however, some native toolkits may choose a different virtual screen area.
+ * </p>
+ * @param result storage for result, will be returned
*/
- public abstract ScreenMode getOriginalScreenMode();
+ public final Rectangle unionOfMonitorViewportSize(final Rectangle result) {
+ return MonitorDevice.unionOfViewports(result, getMonitorDevices());
+ }
/**
- * Return the current {@link com.jogamp.newt.ScreenMode}.
- * <p>
- * If {@link com.jogamp.newt.ScreenMode ScreenMode}s are not supported for this
- * native type {@link com.jogamp.newt.Display#getType()}, it returns one with the current screen size. </p>
- *
- * @return current ScreenMode which is element of the list {@link #getScreenModes()}.
+ * @param sml {@link MonitorModeListener} to be added for {@link MonitorEvent}
*/
- public abstract ScreenMode getCurrentScreenMode();
+ public abstract void addMonitorModeListener(MonitorModeListener sml);
/**
- * Set the current {@link com.jogamp.newt.ScreenMode}.
- * @param screenMode to be made current, must be element of the list {@link #getScreenModes()}.
- * @return true if successful, otherwise false
+ * @param sml {@link MonitorModeListener} to be removed from {@link MonitorEvent}
*/
- public abstract boolean setCurrentScreenMode(ScreenMode screenMode);
+ public abstract void removeMonitorModeListener(MonitorModeListener sml);
// Global Screens
- protected static ArrayList<Screen> screenList = new ArrayList<Screen>();
+ protected static final ArrayList<WeakReference<Screen>> screenList = new ArrayList<WeakReference<Screen>>();
protected static int screensActive = 0;
/**
@@ -223,21 +257,56 @@ public abstract class Screen {
synchronized(screenList) {
int i = fromIndex >= 0 ? fromIndex : screenList.size() - 1 ;
while( ( incr > 0 ) ? i < screenList.size() : i >= 0 ) {
- Screen screen = (Screen) screenList.get(i);
- if( screen.getDisplay().equals(display) &&
- screen.getIndex() == idx ) {
- return screen;
+ final Screen screen = (Screen) screenList.get(i).get();
+ if( null == screen ) {
+ // Clear GC'ed dead reference entry!
+ screenList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( screen.getDisplay().equals(display) &&
+ screen.getIndex() == idx ) {
+ return screen;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
- /** Returns the global display collection */
+
+ protected static void addScreen2List(Screen screen) {
+ synchronized(screenList) {
+ // GC before add
+ int i=0;
+ while( i < screenList.size() ) {
+ if( null == screenList.get(i).get() ) {
+ screenList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ screenList.add(new WeakReference<Screen>(screen));
+ }
+ }
+
+ /** Returns the global screen collection */
public static Collection<Screen> getAllScreens() {
ArrayList<Screen> list;
synchronized(screenList) {
- list = (ArrayList<Screen>) screenList.clone();
+ list = new ArrayList<Screen>();
+ int i = 0;
+ while( i < screenList.size() ) {
+ final Screen s = screenList.get(i).get();
+ if( null == s ) {
+ screenList.remove(i);
+ } else {
+ list.add( screenList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
diff --git a/src/newt/classes/com/jogamp/newt/ScreenMode.java b/src/newt/classes/com/jogamp/newt/ScreenMode.java
deleted file mode 100644
index 1f12217bb..000000000
--- a/src/newt/classes/com/jogamp/newt/ScreenMode.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/**
- * Copyright 2010 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 com.jogamp.newt;
-
-import javax.media.nativewindow.util.DimensionImmutable;
-
-import com.jogamp.newt.util.MonitorMode;
-
-/** Immutable ScreenMode Class, consisting of it's read only components:<br>
- * <ul>
- * <li>{@link com.jogamp.newt.util.MonitorMode}, non rotated values</li>
- * <li><code>rotation</code>, measured counter clockwise (CCW)</li>
- * </ul>
- *
- * <i>Aquire and filter ScreenModes</i><br>
- * <ul>
- * <li>A List of read only ScreenMode's is being returned by {@link com.jogamp.newt.Screen#getScreenModes()}.</li>
- * <li>You may utilize {@link com.jogamp.newt.util.ScreenModeUtil} to filter and select a desired ScreenMode.</li>
- * <li>The current ScreenMode can be obtained via {@link com.jogamp.newt.Screen#getCurrentScreenMode()}.</li>
- * <li>The initial original ScreenMode (at startup) can be obtained via {@link com.jogamp.newt.Screen#getOriginalScreenMode()}.</li>
- * </ul>
- * <br>
- *
- * <i>Changing ScreenModes</i><br>
- * <ul>
- * <li> Use {@link com.jogamp.newt.Screen#setCurrentScreenMode(com.jogamp.newt.ScreenMode)}</li>
- * to change the current ScreenMode of all Screen's referenced via the full qualified name (FQN)
- * {@link com.jogamp.newt.Screen#getFQName()}.</li>
- * <li> When the last FQN referenced Screen closes, the original ScreenMode ({@link com.jogamp.newt.Screen#getOriginalScreenMode()})
- * is restored.</li>
- * </ul>
- * <br>
- * Example for changing the ScreenMode:
- * <pre>
- // determine target refresh rate
- ScreenMode orig = screen.getOriginalScreenMode();
- int freq = orig.getMonitorMode().getRefreshRate();
-
- // target resolution
- Dimension res = new Dimension(800, 600);
-
- // target rotation
- int rot = 0;
-
- // filter available ScreenModes
- List screenModes = screen.getScreenModes();
- screenModes = ScreenModeUtil.filterByRate(screenModes, freq); // get the nearest ones
- screenModes = ScreenModeUtil.filterByRotation(screenModes, rot);
- screenModes = ScreenModeUtil.filterByResolution(screenModes, res); // get the nearest ones
- screenModes = ScreenModeUtil.getHighestAvailableBpp(screenModes);
-
- // pick 1st one ..
- screen.setCurrentScreenMode((ScreenMode) screenModes.get(0));
- * </pre>
- *
- * X11 / AMD just works<br>
- * <br>
- * X11 / NVidia difficulties
- * <pre>
- NVidia RANDR RefreshRate Bug
- If NVidia's 'DynamicTwinView' is enabled, all refresh rates are
- unique, ie consequent numbers starting with the default refresh, ie 50, 51, ..
- The only way to workaround it is to disable 'DynamicTwinView'.
- Read: http://us.download.nvidia.com/XFree86/Linux-x86/260.19.12/README/configtwinview.html
-
- Check to see if 'DynamicTwinView' is enable:
- nvidia-settings -q :0/DynamicTwinview
-
- To disable it (workaround), add the following option to your xorg.conf device section:
- Option "DynamicTwinView" "False"
-
- NVidia RANDR Rotation:
- To enable it, add the following option to your xorg.conf device section:
- Option "RandRRotation" "on"
- * </pre>
- *
- */
-public class ScreenMode {
- /** zero rotation, compared to normal settings */
- public static final int ROTATE_0 = 0;
-
- /** 90 degrees CCW rotation */
- public static final int ROTATE_90 = 90;
-
- /** 180 degrees CCW rotation */
- public static final int ROTATE_180 = 180;
-
- /** 270 degrees CCW rotation */
- public static final int ROTATE_270 = 270;
-
- MonitorMode monitorMode;
- int rotation;
-
- public static boolean isRotationValid(int rotation) {
- return rotation == ScreenMode.ROTATE_0 || rotation == ScreenMode.ROTATE_90 ||
- rotation == ScreenMode.ROTATE_180 || rotation == ScreenMode.ROTATE_270 ;
- }
-
- /**
- * @param monitorMode the monitor mode
- * @param rotation the screen rotation, measured counter clockwise (CCW)
- */
- public ScreenMode(MonitorMode monitorMode, int rotation) {
- if ( !isRotationValid(rotation) ) {
- throw new RuntimeException("invalid rotation: "+rotation);
- }
- this.monitorMode = monitorMode;
- this.rotation = rotation;
- }
-
- /** Returns the unrotated <code>MonitorMode</code> */
- public final MonitorMode getMonitorMode() {
- return monitorMode;
- }
-
- /** Returns the CCW rotation of this mode */
- public final int getRotation() {
- return rotation;
- }
-
- /** Returns the rotated screen width,
- * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
- * and <code>getRotation()</code>
- */
- public final int getRotatedWidth() {
- return getRotatedWH(true);
- }
-
- /** Returns the rotated screen height,
- * derived from <code>getMonitorMode().getSurfaceSize().getResolution()</code>
- * and <code>getRotation()</code>
- */
- public final int getRotatedHeight() {
- return getRotatedWH(false);
- }
-
- public final String toString() {
- return "[ " + getMonitorMode() + ", " + rotation + " degr ]";
- }
-
- /**
- * Tests equality of two <code>ScreenMode</code> objects
- * by evaluating equality of it's components:<br>
- * <ul>
- * <li><code>monitorMode</code></li>
- * <li><code>rotation</code></li>
- * </ul>
- * <br>
- */
- public final boolean equals(Object obj) {
- if (this == obj) { return true; }
- if (obj instanceof ScreenMode) {
- ScreenMode sm = (ScreenMode)obj;
- return sm.getMonitorMode().equals(getMonitorMode()) &&
- sm.getRotation() == this.getRotation() ;
- }
- return false;
- }
-
- /**
- * Returns a combined hash code of it's elements:<br>
- * <ul>
- * <li><code>monitorMode</code></li>
- * <li><code>rotation</code></li>
- * </ul>
- */
- public final int hashCode() {
- // 31 * x == (x << 5) - x
- int hash = 31 + getMonitorMode().hashCode();
- hash = ((hash << 5) - hash) + getRotation();
- return hash;
- }
-
- private final int getRotatedWH(boolean width) {
- final DimensionImmutable d = getMonitorMode().getSurfaceSize().getResolution();
- final boolean swap = ScreenMode.ROTATE_90 == rotation || ScreenMode.ROTATE_270 == rotation ;
- if ( ( width && swap ) || ( !width && !swap ) ) {
- return d.getHeight();
- }
- return d.getWidth();
- }
-}
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 3c5441bf7..4816e62e5 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -28,20 +28,56 @@
package com.jogamp.newt;
+import java.util.List;
+
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.MouseListener;
+
import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
+
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.RectangleImmutable;
/**
- * Specifying the public Window functionality for the
- * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}.
+ * Specifying NEWT's Window functionality:
+ * <ul>
+ * <li>On- and offscreen windows</li>
+ * <li>Keyboard and multi-pointer input</li>
+ * <li>Native reparenting</li>
+ * <li>Toggable fullscreen and decoration mode</li>
+ * <li>Transparency</li>
+ * <li>... and more</li>
+ * </ul>
+ * <p>
+ * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates
+ * window operation to an instance of this interface while providing OpenGL
+ * functionality.
+ * </p>
+ * <a name="customwindowicons"><h5>Custom Window Icons</h5></a>
+ * <p>
+ * Custom window icons can be defined via system property <code>newt.window.icons</code>,
+ * which shall contain a space separated list of PNG icon locations from low- to high-resolution.
+ * The location must be resolvable via classpath, i.e. shall reference a location within the jar file.
+ * Example (our default):
+ * <pre>
+ * -Dnewt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
+ * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
+ * </pre>
+ * The property can also be set programmatically, which must happen before any NEWT classes are <i>touched</i>:
+ * <pre>
+ * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png");
+ * </pre>
+ * </p>
*/
public interface Window extends NativeWindow, WindowClosingProtocol {
public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent");
@@ -65,13 +101,22 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
boolean isNativeValid();
/**
- * @return The associated Screen
+ * @return The associated {@link Screen}
*/
Screen getScreen();
/**
+ * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport}
+ * {@link MonitorDevice#coverage(RectangleImmutable) covers} this window the most.
+ * <p>
+ * If no coverage is detected the first {@link MonitorDevice} is returned.
+ * </p>
+ */
+ MonitorDevice getMainMonitor();
+
+ /**
* Set the CapabilitiesChooser to help determine the native visual type.
- *
+ *
* @param chooser the new CapabilitiesChooser
* @return the previous CapabilitiesChooser
*/
@@ -86,37 +131,71 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
/**
* Gets an immutable set of chosen capabilities.
- *
+ *
* @return the chosen capabilities
*/
CapabilitiesImmutable getChosenCapabilities();
/**
- * Destroy the Window and it's children, incl. native destruction.<br>
- * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
- * <p>Visibility is set to false.</p>
+ * {@inheritDoc}
+ * <p>
+ * Also iterates through this window's children and destroys them.
+ * </p>
+ * <p>
+ * Visibility is set to false.
+ * </p>
+ * <p>
+ * Method sends out {@link WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY pre-} and
+ * {@link WindowEvent#EVENT_WINDOW_DESTROYED post-} destruction events
+ * to all of it's {@link WindowListener}.
+ * </p>
* <p>
* This method invokes {@link Screen#removeReference()} after it's own destruction,<br>
* which will issue {@link Screen#destroy()} if the reference count becomes 0.<br>
* This destruction sequence shall end up in {@link Display#destroy()}, if all reference counts become 0.
* </p>
+ * <p>
+ * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
+ * </p>
* @see #destroy()
* @see #setVisible(boolean)
*/
+ @Override
void destroy();
/**
+ * Set a custom action handling destruction issued by a {@link WindowImpl#windowDestroyNotify(boolean) toolkit triggered window destroy}
+ * replacing the default {@link #destroy()} action.
* <p>
- * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true,
- * otherwise the window and children becomes invisible.<br></p>
+ * The custom action shall call {@link #destroy()}
+ * but may perform further tasks before and after.
+ * </p>
+ */
+ void setWindowDestroyNotifyAction(Runnable r);
+
+ /**
+ * Calls {@link #setVisible(boolean, boolean) setVisible(true, visible)},
+ * i.e. blocks until the window becomes visible.
+ * @see #setVisible(boolean, boolean)
+ */
+ void setVisible(boolean visible);
+
+ /**
+ * <code>setVisible(..)</code> makes the window and children visible if <code>visible</code> is true,
+ * otherwise the window and children becomes invisible.
+ * <p>
+ * <code>setVisible(wait, true)</code> is responsible to actual create the native window.
+ * </p>
* <p>
- * The <code>setVisible(true)</code> is responsible to actual create the native window.<br></p>
+ * If <code>wait</code> is true, method blocks until window is {@link #isVisible() visible} and {@link #isNativeValid() valid},
+ * otherwise method returns immediately.
+ * </p>
* <p>
* Zero size semantics are respected, see {@link #setSize(int,int)}:<br>
* <pre>
* if ( 0 == windowHandle && visible ) {
* this.visible = visible;
- * if( 0 &lt; width*height ) {
+ * if( 0 &lt; width && 0 &lt; height ) {
* createNative();
* }
* } else if ( this.visible != visible ) {
@@ -125,23 +204,24 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* }
* </pre></p>
* <p>
- * In case this window is a child window and a parent {@link javax.media.nativewindow.NativeWindow} is being used,<br>
- * the parent's {@link javax.media.nativewindow.NativeWindow} handle is retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.<br>
- * If this action fails, ie if the parent {@link javax.media.nativewindow.NativeWindow} is not valid yet,<br>
- * no native window is created yet and <code>setVisible(true)</code> shall be repeated when it is.<br></p>
+ * In case this window is a child window and has a {@link javax.media.nativewindow.NativeWindow} parent,<br>
+ * <code>setVisible(wait, true)</code> has no effect as long the parent's is not valid yet,
+ * i.e. {@link javax.media.nativewindow.NativeWindow#getWindowHandle()} returns <code>null</code>.<br>
+ * <code>setVisible(wait, true)</code> shall be repeated when the parent becomes valid.
+ * </p>
*/
- void setVisible(boolean visible);
+ void setVisible(boolean wait, boolean visible);
boolean isVisible();
- /**
- * If the implementation uses delegation, return the delegated {@link Window} instance,
+ /**
+ * If the implementation uses delegation, return the delegated {@link Window} instance,
* otherwise return <code>this</code> instance. */
Window getDelegatedWindow();
-
+
//
// Child Window Management
- //
+ //
boolean addChild(NativeWindow win);
@@ -153,13 +233,13 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
/**
* Sets the size of the window's client area, excluding decorations.
- *
+ *
* <p>
* Zero size semantics are respected, see {@link #setVisible(boolean)}:<br>
* <pre>
- * if ( 0 != windowHandle && 0 &ge; width*height && visible ) {
+ * if ( visible && 0 != windowHandle && ( 0 &ge; width || 0 &ge; height ) ) {
* setVisible(false);
- * } else if ( 0 == windowHandle && 0 &lt; width*height && visible ) {
+ * } else if ( visible && 0 == windowHandle && 0 &lt; width && 0 &lt; height ) {
* setVisible(true);
* } else {
* // as expected ..
@@ -170,105 +250,121 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*
* @param width of the window's client area
* @param height of the window's client area
- *
+ *
* @see #getInsets()
*/
void setSize(int width, int height);
/**
* Sets the size of the top-level window including insets (window decorations).
- *
+ *
* <p>
* Note: Insets (if supported) are available only after the window is set visible and hence has been created.
* </p>
*
* @param width of the top-level window area
* @param height of the top-level window area
- *
+ *
* @see #setSize(int, int)
* @see #getInsets()
*/
void setTopLevelSize(int width, int height);
-
+
/**
* Sets the location of the window's client area, excluding insets (window decorations).<br>
- *
+ *
* This call is ignored if in fullscreen mode.<br>
*
* @param x coord of the client-area's top left corner
* @param y coord of the client-area's top left corner
- *
+ *
* @see #getInsets()
*/
void setPosition(int x, int y);
-
+
/**
* Sets the location of the top-level window inclusive insets (window decorations).<br>
- *
+ *
* <p>
* Note: Insets (if supported) are available only after the window is set visible and hence has been created.
* </p>
- *
+ *
* This call is ignored if in fullscreen mode.<br>
*
* @param x coord of the top-level left corner
* @param y coord of the top-level left corner
- *
+ *
* @see #setPosition(int, int)
* @see #getInsets()
*/
void setTopLevelPosition(int x, int y);
void setUndecorated(boolean value);
-
+
boolean isUndecorated();
-
+
void setAlwaysOnTop(boolean value);
-
+
boolean isAlwaysOnTop();
-
+
void setTitle(String title);
String getTitle();
+ /** @see #setPointerVisible(boolean) */
boolean isPointerVisible();
-
+
/**
* Makes the pointer visible or invisible.
- *
+ *
* @param pointerVisible defaults to <code>true</code> for platforms w/ visible pointer,
* otherwise defaults to <code>true</code>, eg. Android.
* @see #confinePointer(boolean)
*/
void setPointerVisible(boolean pointerVisible);
+ /**
+ * Returns the current {@link PointerIcon}, which maybe <code>null</code> for the default.
+ * @see #setPointerIcon(PointerIcon)
+ */
+ PointerIcon getPointerIcon();
+
+ /**
+ * @param pi Valid {@link PointerIcon} reference or <code>null</code> to reset the pointer icon to default.
+ *
+ * @see PointerIcon
+ * @see Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int)
+ */
+ void setPointerIcon(final PointerIcon pi);
+
+ /** @see #confinePointer(boolean) */
boolean isPointerConfined();
-
+
/**
* Confine the pointer to this window, ie. pointer jail.
* <p>
- * Before jailing the mouse pointer,
+ * Before jailing the mouse pointer,
* the window request the focus and the pointer is centered in the window.
* </p>
* <p>
- * In combination w/ {@link #warpPointer(int, int)}
+ * In combination w/ {@link #warpPointer(int, int)}
* and maybe {@link #setPointerVisible(boolean)} a simple mouse
* navigation can be realized.</p>
- *
+ *
* @param confine defaults to <code>false</code>.
*/
void confinePointer(boolean confine);
-
+
/**
* Moves the pointer to x/y relative to this window's origin.
- *
+ *
* @param x relative pointer x position within this window
* @param y relative pointer y position within this window
- *
+ *
* @see #confinePointer(boolean)
*/
void warpPointer(int x, int y);
-
+
/** Reparenting operation types */
public enum ReparentOperation {
/** No native reparenting valid */
@@ -284,9 +380,14 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
ACTION_NATIVE_CREATION,
/** Change Window tree only, native creation is pending */
- ACTION_NATIVE_CREATION_PENDING;
+ ACTION_NATIVE_CREATION_PENDING;
}
+ /** Reparenting hint (bitfield value): Force destroy and hence {@link ReparentOperation#ACTION_NATIVE_CREATION re-creating} the window. */
+ public static final int REPARENT_HINT_FORCE_RECREATION = 1 << 0;
+ /** Reparenting hint (bitfield value): Claim window becomes visible after reparenting, which is important for e.g. preserving the GL-states in case window is invisible while reparenting. */
+ public static final int REPARENT_HINT_BECOMES_VISIBLE = 1 << 1;
+
/**
* Change this window's parent window.<br>
* <P>
@@ -298,13 +399,72 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* @param newParent The new parent NativeWindow. If null, this Window becomes a top level window.
*
* @return The issued reparent action type (strategy) as defined in Window.ReparentAction
+ * @see #reparentWindow(NativeWindow, int, int, boolean)
+ * @deprecated Use {@link #reparentWindow(NativeWindow, int, int, int)}
*/
ReparentOperation reparentWindow(NativeWindow newParent);
- ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate);
+ /**
+ * Change this window's parent window.<br>
+ * <P>
+ * In case the old parent is not null and a Window,
+ * this window is removed from it's list of children.<br>
+ * In case the new parent is not null and a Window,
+ * this window is added to it's list of children.<br></P>
+ *
+ * @param newParent The new parent NativeWindow. If null, this Window becomes a top level window.
+ * @param x new top-level position, use -1 for default position.
+ * @param y new top-level position, use -1 for default position.
+ * @param forceDestroyCreate if true, uses re-creation strategy for reparenting, default is <code>false</code>.
+ *
+ * @return The issued reparent action type (strategy) as defined in Window.ReparentAction
+ * @deprecated Use {@link #reparentWindow(NativeWindow, int, int, int)}
+ */
+ ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, boolean forceDestroyCreate);
+ /**
+ * Change this window's parent window.<br>
+ * <P>
+ * In case the old parent is not null and a Window,
+ * this window is removed from it's list of children.<br>
+ * In case the new parent is not null and a Window,
+ * this window is added to it's list of children.<br></P>
+ *
+ * @param newParent The new parent NativeWindow. If null, this Window becomes a top level window.
+ * @param x new top-level position, use -1 for default position.
+ * @param y new top-level position, use -1 for default position.
+ * @param hints May contain hints (bitfield values) like {@link #REPARENT_HINT_FORCE_RECREATION} or {@link #REPARENT_HINT_BECOMES_VISIBLE}.
+ *
+ * @return The issued reparent action type (strategy) as defined in Window.ReparentAction
+ */
+ ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints);
+
+ /**
+ * Enable or disable fullscreen mode for this window.
+ * <p>
+ * Fullscreen mode is established on the {@link #getMainMonitor() main monitor}.
+ * </p>
+ * @param fullscreen enable or disable fullscreen mode
+ * @return success
+ * @see #setFullscreen(List)
+ * @see #isFullscreen()
+ */
boolean setFullscreen(boolean fullscreen);
-
+
+ /**
+ * Enable fullscreen mode for this window spanning across the given {@link MonitorDevice}s
+ * or across all {@link MonitorDevice}s.
+ * <p>
+ * Disable fullscreen via {@link #setFullscreen(boolean)}.
+ * </p>
+ * @param monitors if <code>null</code> fullscreen will be spanned across all {@link MonitorDevice}s,
+ * otherwise across the given list of {@link MonitorDevice}.
+ * @return success
+ * @see #setFullscreen(boolean)
+ * @see #isFullscreen()
+ */
+ boolean setFullscreen(List<MonitorDevice> monitors);
+
boolean isFullscreen();
static interface FocusRunnable {
@@ -316,7 +476,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
}
/**
- * Sets a {@link FocusRunnable},
+ * Sets a {@link FocusRunnable},
* which {@link FocusRunnable#run()} method is executed before the native focus is requested.
* <p>
* This allows notifying a covered window toolkit like AWT that the focus is requested,
@@ -324,38 +484,42 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* </p>
*/
void setFocusAction(FocusRunnable focusAction);
-
+
/**
* Sets a {@link KeyListener} allowing focus traversal with a covered window toolkit like AWT.
* <p>
* The {@link KeyListener} methods are invoked prior to all other {@link KeyListener}'s
- * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}.
+ * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}
+ * and to perform focus traversal with a 3rd party toolkit.
+ * </p>
+ * <p>
+ * The {@link KeyListener} methods are not invoked for {@link KeyEvent#isAutoRepeat() auto-repeat} events.
* </p>
* @param l
*/
void setKeyboardFocusHandler(KeyListener l);
- /**
+ /**
* Request focus for this native window
* <p>
* The request is handled on this Window EDT and blocked until finished.
* </p>
- *
+ *
* @see #requestFocus(boolean)
*/
void requestFocus();
- /**
+ /**
* Request focus for this native window
* <p>
- * The request is handled on this Window EDT.
+ * The request is handled on this Window EDT.
* </p>
- *
+ *
* @param wait true if waiting until the request is executed, otherwise false
* @see #requestFocus()
*/
void requestFocus(boolean wait);
-
+
void windowRepaint(int x, int y, int width, int height);
void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event);
@@ -367,10 +531,13 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
// WindowListener
//
+ /**
+ * Send a {@link WindowEvent} to all {@link WindowListener}.
+ * @param eventType a {@link WindowEvent} type, e.g. {@link WindowEvent#EVENT_WINDOW_REPAINT}.
+ */
public void sendWindowEvent(int eventType);
/**
- *
* Appends the given {@link com.jogamp.newt.event.WindowListener} to the end of
* the list.
*/
@@ -399,6 +566,26 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
// KeyListener
//
+ /**
+ * In case the platform supports or even requires a virtual on-screen keyboard,
+ * this method shows or hide it depending on whether <code>visible</code> is <code>true</code>
+ * or <code>false</code>.
+ * <p>
+ * One known platform where NEWT supports this feature is <code>Android</code>.
+ * </p>
+ */
+ void setKeyboardVisible(boolean visible);
+
+ /**
+ * Return <code>true</code> if the virtual on-screen keyboard is visible, otherwise <code>false</code>.
+ * <p>
+ * Currently on <code>Android</code>, the only supported platform right now,
+ * there is no way to reliably be notified of the current keyboard state.<br>
+ * It would be best, if your code does not rely on this information.
+ * </p>
+ * @see #setKeyboardVisible(boolean)
+ */
+ boolean isKeyboardVisible();
/**
*
@@ -432,15 +619,12 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
//
/**
- *
- * Appends the given {@link com.jogamp.newt.event.MouseListener} to the end of
- * the list.
+ * Appends the given {@link MouseListener} to the end of the list.
*/
void addMouseListener(MouseListener l);
/**
- *
- * Inserts the given {@link com.jogamp.newt.event.MouseListener} at the
+ * Inserts the given {@link MouseListener} at the
* specified position in the list.<br>
*
* @param index Position where the listener will be inserted.
@@ -451,10 +635,61 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
*/
void addMouseListener(int index, MouseListener l);
+ /**
+ * Removes the given {@link MouseListener} from the list.
+ */
void removeMouseListener(MouseListener l);
+ /**
+ * Returns the {@link MouseListener} from the list at the given index.
+ */
MouseListener getMouseListener(int index);
+ /**
+ * Returns all {@link MouseListener}
+ */
MouseListener[] getMouseListeners();
+ /** Enable or disable default {@link GestureHandler}. Default is enabled. */
+ void setDefaultGesturesEnabled(boolean enable);
+ /** Return true if default {@link GestureHandler} are enabled. */
+ boolean areDefaultGesturesEnabled();
+ /**
+ * Appends the given {@link GestureHandler} to the end of the list.
+ */
+ void addGestureHandler(GestureHandler gh);
+ /**
+ * Inserts the given {@link GestureHandler} at the
+ * specified position in the list.<br>
+ *
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param l The listener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ void addGestureHandler(int index, GestureHandler gh);
+ /**
+ * Removes the given {@link GestureHandler} from the list.
+ */
+ void removeGestureHandler(GestureHandler gh);
+ /**
+ * Appends the given {@link GestureHandler.GestureListener} to the end of the list.
+ */
+ void addGestureListener(GestureHandler.GestureListener gl);
+ /**
+ * Inserts the given {@link GestureHandler.GestureListener} at the
+ * specified position in the list.<br>
+ *
+ * @param index Position where the listener will be inserted.
+ * Should be within (0 <= index && index <= size()).
+ * An index value of -1 is interpreted as the end of the list, size().
+ * @param l The listener object to be inserted
+ * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1
+ */
+ void addGestureListener(int index, GestureHandler.GestureListener gl);
+ /**
+ * Removes the given {@link GestureHandler.GestureListener} from the list.
+ */
+ void removeGestureListener(GestureHandler.GestureListener gl);
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 9af4a02ae..1ed628435 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,20 +20,26 @@
* 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 com.jogamp.newt.awt;
+import java.applet.Applet;
import java.awt.AWTKeyStroke;
import java.awt.Canvas;
+import java.awt.Component;
+import java.awt.EventQueue;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.KeyboardFocusManager;
+import java.awt.geom.NoninvertibleTransformException;
+import java.beans.Beans;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
@@ -44,19 +50,28 @@ import java.util.Set;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.OffscreenLayerOption;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.swing.MenuSelectionManager;
import jogamp.nativewindow.awt.AWTMisc;
+import jogamp.nativewindow.jawt.JAWTUtil;
import jogamp.newt.Debug;
+import jogamp.newt.WindowImpl;
import jogamp.newt.awt.NewtFactoryAWT;
import jogamp.newt.awt.event.AWTParentWindowAdapter;
import jogamp.newt.driver.DriverClearFocus;
+import jogamp.opengl.awt.AWTTilePainter;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
+import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.newt.Display;
import com.jogamp.newt.Window;
-import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.WindowAdapter;
@@ -65,32 +80,68 @@ import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTKeyAdapter;
import com.jogamp.newt.event.awt.AWTMouseAdapter;
+import com.jogamp.opengl.util.GLDrawableUtil;
+import com.jogamp.opengl.util.TileRenderer;
+/**
+ * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting.
+ *
+ * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5>
+ *
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
+ * the underlying JAWT mechanism to composite the image, if supported.
+ */
@SuppressWarnings("serial")
-public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption {
+public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
public static final boolean DEBUG = Debug.debug("Window");
+ private final Object sync = new Object();
private JAWTWindow jawtWindow = null;
+ private boolean isApplet = false;
private boolean shallUseOffscreenLayer = false;
private Window newtChild = null;
+ private boolean newtChildAttached = false;
private boolean isOnscreen = true;
private WindowClosingMode newtChildCloseOp;
- private AWTAdapter awtAdapter = null;
- private AWTAdapter awtMouseAdapter = null;
- private AWTAdapter awtKeyAdapter = null;
-
- private AWTWindowClosingProtocol awtWindowClosingProtocol =
+ private final AWTParentWindowAdapter awtAdapter;
+ private final AWTAdapter awtMouseAdapter;
+ private final AWTAdapter awtKeyAdapter;
+
+ /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
+ private boolean destroyJAWTPending = false;
+ /** Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy(). */
+ private boolean skipJAWTDestroy = false;
+
+ /** Safeguard for AWTWindowClosingProtocol and 'removeNotify()' on other thread than AWT-EDT. */
+ private volatile boolean componentAdded = false;
+
+ private final AWTWindowClosingProtocol awtWindowClosingProtocol =
new AWTWindowClosingProtocol(this, new Runnable() {
+ @Override
public void run() {
- NewtCanvasAWT.this.destroy();
+ if( componentAdded ) {
+ NewtCanvasAWT.this.destroyImpl(false /* removeNotify */, true /* windowClosing */);
+ }
+ }
+ }, new Runnable() {
+ @Override
+ public void run() {
+ if( componentAdded && newtChild != null ) {
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ }
}
- });
+ } );
/**
* Instantiates a NewtCanvas without a NEWT child.<br>
*/
public NewtCanvasAWT() {
super();
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
}
/**
@@ -98,6 +149,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
*/
public NewtCanvasAWT(GraphicsConfiguration gc) {
super(gc);
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
}
/**
@@ -105,6 +160,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
*/
public NewtCanvasAWT(Window child) {
super();
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
setNEWTChild(child);
}
@@ -113,142 +172,173 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
*/
public NewtCanvasAWT(GraphicsConfiguration gc, Window child) {
super(gc);
+ awtMouseAdapter = new AWTMouseAdapter().addTo(this);
+ awtKeyAdapter = new AWTKeyAdapter().addTo(this);
+ awtAdapter = (AWTParentWindowAdapter) new AWTParentWindowAdapter().addTo(this);
+ awtAdapter.removeWindowClosingFrom(this); // we utilize AWTWindowClosingProtocol triggered destruction!
setNEWTChild(child);
}
-
+
+ @Override
public void setShallUseOffscreenLayer(boolean v) {
shallUseOffscreenLayer = v;
}
-
+
+ @Override
public final boolean getShallUseOffscreenLayer() {
- return shallUseOffscreenLayer;
+ return shallUseOffscreenLayer;
}
-
- public final boolean isOffscreenLayerSurfaceEnabled() {
- return jawtWindow.isOffscreenLayerSurfaceEnabled();
+
+ @Override
+ public final boolean isOffscreenLayerSurfaceEnabled() {
+ final JAWTWindow w = jawtWindow;
+ return null != w && w.isOffscreenLayerSurfaceEnabled();
}
-
- /**
- * Returns true if the AWT component is parented to an {@link java.applet.Applet},
- * otherwise false. This information is valid only after {@link #addNotify()} is issued,
- * ie. before adding the component to the AWT tree and make it visible.
+
+ /**
+ * Returns true if the AWT component is parented to an {@link java.applet.Applet},
+ * otherwise false. This information is valid only after {@link #addNotify()} is issued.
*/
- public boolean isApplet() {
- return jawtWindow.isApplet();
+ public final boolean isApplet() {
+ return isApplet;
}
- boolean isParent() {
- return null!=newtChild && jawtWindow == newtChild.getParent();
+ private final boolean isParent() {
+ final Window nw = newtChild;
+ return null!=nw && jawtWindow == nw.getParent();
}
-
- boolean isFullscreen() {
- return null != newtChild && newtChild.isFullscreen();
+
+ private final boolean isFullscreen() {
+ final Window nw = newtChild;
+ return null != nw && nw.isFullscreen();
}
-
+
class FocusAction implements Window.FocusRunnable {
+ @Override
public boolean run() {
final boolean isParent = isParent();
final boolean isFullscreen = isFullscreen();
if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen);
}
- if(isParent && !isFullscreen) {
- // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- if(!hasFocus()) {
- // Acquire the AWT focus 1st for proper AWT traversal
- NewtCanvasAWT.super.requestFocus();
- }
- if(isOnscreen) {
+ if( isParent && !isFullscreen ) { // must be parent of newtChild _and_ newtChild not fullscreen
+ if( isOnscreen ) {
// Remove the AWT focus in favor of the native NEWT focus
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
+ } else if( !hasFocus() ) {
+ // In offscreen mode we require the focus!
+ // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
+ NewtCanvasAWT.super.requestFocus();
}
}
return false; // NEWT shall proceed requesting the native focus
}
}
- private FocusAction focusAction = new FocusAction();
-
- WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
+ private final FocusAction focusAction = new FocusAction();
+
+ private static class ClearFocusOwner implements Runnable {
+ @Override
+ public void run() {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+ }
+ private static final Runnable awtClearGlobalFocusOwner = new ClearFocusOwner();
+
+ /** Must run on AWT-EDT non-blocking, since it invokes tasks on AWT-EDT w/ waiting otherwise. */
+ private final Runnable awtClearSelectedMenuPath = new Runnable() {
+ @Override
+ public void run() {
+ MenuSelectionManager.defaultManager().clearSelectedPath();
+ }
+ };
+ private final WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() {
+ @Override
+ public void windowResized(WindowEvent e) {
+ updateLayoutSize();
+ }
@Override
public void windowGainedFocus(WindowEvent arg0) {
if( isParent() && !isFullscreen() ) {
- MenuSelectionManager.defaultManager().clearSelectedPath();
+ AWTEDTExecutor.singleton.invoke(false, awtClearSelectedMenuPath);
}
}
};
class FocusTraversalKeyListener implements KeyListener {
- boolean suppress = false;
-
+ @Override
public void keyPressed(KeyEvent e) {
if( isParent() && !isFullscreen() ) {
handleKey(e, false);
}
}
+ @Override
public void keyReleased(KeyEvent e) {
if( isParent() && !isFullscreen() ) {
handleKey(e, true);
}
}
- public void keyTyped(KeyEvent e) {
- if(suppress) {
- e.setAttachment(InputEvent.consumedTag);
- suppress = false; // reset
- }
- }
-
- void handleKey(KeyEvent evt, boolean onRelease) {
+
+ void handleKey(KeyEvent evt, boolean onRelease) {
if(null == keyboardFocusManager) {
throw new InternalError("XXX");
}
final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
+ boolean suppress = false;
if(null != ks) {
- final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
- final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
if(fwdKeys.contains(ks)) {
+ final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocus();
+ nextFocus.requestFocus();
suppress = true;
} else if(bwdKeys.contains(ks)) {
+ final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocusBackward();
+ prevFocus.requestFocus();
suppress = true;
}
}
if(suppress) {
- evt.setAttachment(InputEvent.consumedTag);
+ evt.setConsumed(true);
}
if(DEBUG) {
System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks);
}
}
}
- private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
+ private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener();
class FocusPropertyChangeListener implements PropertyChangeListener {
+ @Override
public void propertyChange(PropertyChangeEvent evt) {
final Object oldF = evt.getOldValue();
final Object newF = evt.getNewValue();
final boolean isParent = isParent();
- final boolean isFullscreen = isFullscreen();
+ final boolean isFullscreen = isFullscreen();
if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF+", isParent "+isParent+", isFS "+isFullscreen);
}
if(isParent && !isFullscreen) {
- if(oldF == NewtCanvasAWT.this && newF == null) {
+ if(newF == NewtCanvasAWT.this) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.FocusProperty: AWT focus -> NEWT focus traversal");
+ }
+ requestFocusNEWTChild();
+ } else if(oldF == NewtCanvasAWT.this && newF == null) {
// focus traversal to NEWT - NOP
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus traversal");
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus");
}
} else if(null != newF && newF != NewtCanvasAWT.this) {
// focus traversal to another AWT component
- if(DEBUG) {
+ if(DEBUG) {
System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus");
}
if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) {
@@ -256,22 +346,64 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
- }
+ }
}
private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener();
private volatile KeyboardFocusManager keyboardFocusManager = null;
- /** sets a new NEWT child, provoking reparenting. */
- private NewtCanvasAWT setNEWTChild(Window child) {
- if(newtChild!=child) {
- newtChild = child;
- if(isDisplayable()) {
- // reparent right away, addNotify has been called already
- final java.awt.Container cont = AWTMisc.getContainer(this);
- reparentWindow( (null!=child) ? true : false, cont );
+ private final void requestFocusNEWTChild() {
+ if(null!=newtChild) {
+ newtChild.setFocusAction(null);
+ if(isOnscreen) {
+ AWTEDTExecutor.singleton.invoke(false, awtClearGlobalFocusOwner);
}
+ newtChild.requestFocus();
+ newtChild.setFocusAction(focusAction);
+ }
+ }
+
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(Window newChild) {
+ synchronized(sync) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ final java.awt.Container cont = AWTMisc.getContainer(this);
+ // remove old one
+ if(null != newtChild) {
+ detachNewtChild( cont );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+
+ updateLayoutSize();
+ // will be done later at paint/display/..: attachNewtChild(cont);
+
+ return prevChild;
+ }
+ }
+
+ private final void updateLayoutSize() {
+ final Window w = newtChild;
+ if( null != w ) {
+ // use NEWT child's size for min/pref size!
+ java.awt.Dimension minSize = new java.awt.Dimension(w.getWidth(), w.getHeight());
+ setMinimumSize(minSize);
+ setPreferredSize(minSize);
}
- return this;
}
/** @return the current NEWT child */
@@ -282,145 +414,92 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
/** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called,
* or {@link #addNotify()} hasn't been called yet.*/
public NativeWindow getNativeWindow() { return jawtWindow; }
-
+
+ @Override
public WindowClosingMode getDefaultCloseOperation() {
return awtWindowClosingProtocol.getDefaultCloseOperation();
}
+ @Override
public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
return awtWindowClosingProtocol.setDefaultCloseOperation(op);
}
- /* package */ void configureNewtChild(boolean attach) {
- if(null!=awtAdapter) {
- awtAdapter.removeFrom(this);
- awtAdapter=null;
- }
- if(null!=awtMouseAdapter) {
- awtMouseAdapter.removeFrom(this);
- awtMouseAdapter = null;
- }
- if(null!=awtKeyAdapter) {
- awtKeyAdapter.removeFrom(this);
- awtKeyAdapter = null;
- }
- newtChild.setKeyboardFocusHandler(null);
- if(null != keyboardFocusManager) {
- keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
- keyboardFocusManager = null;
- }
-
- if( null != newtChild ) {
- if(attach) {
- if(null == jawtWindow.getGraphicsConfiguration()) {
- throw new InternalError("XXX");
- }
- isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
- awtAdapter = new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this);
- newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
- newtChild.setFocusAction(focusAction); // enable AWT focus traversal
- newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
- awtWindowClosingProtocol.addClosingListenerOneShot();
- keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
- if(isOnscreen) {
- // onscreen newt child needs to fwd AWT focus
- newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
- } else {
- // offscreen newt child requires AWT to fwd AWT key/mouse event
- awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this);
- awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this);
- }
- } else {
- newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
- newtChild.setFocusAction(null);
- newtChild.setDefaultCloseOperation(newtChildCloseOp);
- awtWindowClosingProtocol.removeClosingListener();
- }
+ /**
+ * Mitigates Bug 910 (IcedTea-Web), i.e. crash via removeNotify() invoked before Applet.destroy().
+ * <p>
+ * <code>skipJAWTDestroy</code> defaults to <code>false</code>.
+ * Due to above IcedTea-Web issue the <code>Applet</code> code needs to avoid JAWT destruction before
+ * <code>Applet.destroy()</code> is reached by setting <code>skipJAWTDestroy</code> to <code>true</code>.
+ * Afterwards the value should be reset to <code>false</code> and {@link #destroy()} needs to be called,
+ * which finally will perform the pending JAWT destruction.
+ * </p>
+ */
+ public final void setSkipJAWTDestroy(boolean v) { skipJAWTDestroy = v; }
+ /** See {@link #setSkipJAWTDestroy(boolean)}. */
+ public final boolean getSkipJAWTDestroy() { return skipJAWTDestroy; }
+
+ private final void determineIfApplet() {
+ isApplet = false;
+ Component c = this;
+ while(!isApplet && null != c) {
+ isApplet = c instanceof Applet;
+ c = c.getParent();
}
}
@Override
public void addNotify() {
-
- // before native peer is valid: X11
- disableBackgroundErase();
-
- // creates the native peer
- super.addNotify();
-
- // after native peer is valid: Windows
- disableBackgroundErase();
-
- java.awt.Container cont = AWTMisc.getContainer(this);
- if(DEBUG) {
- // if ( isShowing() == false ) -> Container was not visible yet.
- // if ( isShowing() == true ) -> Container is already visible.
- System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+
- ", displayable "+isDisplayable()+" -> "+cont);
- }
- reparentWindow(true, cont);
+ if( Beans.isDesignTime() ) {
+ super.addNotify();
+ } else {
+ // before native peer is valid: X11
+ disableBackgroundErase();
+
+ // creates the native peer
+ super.addNotify();
+
+ // after native peer is valid: Windows
+ disableBackgroundErase();
+
+ synchronized(sync) {
+ determineIfApplet();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.addNotify.0 - isApplet "+isApplet+", addedOnAWTEDT "+EventQueue.isDispatchThread()+" @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
+ jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+ awtWindowClosingProtocol.addClosingListener();
+ componentAdded = true; // Bug 910
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.addNotify.X: twin "+newtWinHandleToHexString(newtChild)+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+
+ ", displayable "+isDisplayable()+", cont "+AWTMisc.getContainer(this));
+ }
+ }
+ }
}
@Override
public void removeNotify() {
- java.awt.Container cont = AWTMisc.getContainer(this);
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont);
+ if( Beans.isDesignTime() ) {
+ super.removeNotify();
+ } else {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.removeNotify.0 - isApplet "+isApplet+" @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ componentAdded = false; // Bug 910
+ awtWindowClosingProtocol.removeClosingListener();
+ destroyImpl(true /* removeNotify */, false /* windowClosing */);
+ super.removeNotify();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.removeNotify.X @ "+currentThreadName());
+ }
}
- reparentWindow(false, cont);
- super.removeNotify();
- }
-
- void reparentWindow(boolean add, java.awt.Container cont) {
- if(null==newtChild) {
- return; // nop
- }
-
- newtChild.setFocusAction(null); // no AWT focus traversal ..
- if(add) {
- jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
- jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
- if(DEBUG) {
- System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild);
- }
- final int w;
- final int h;
- if(isPreferredSizeSet()) {
- java.awt.Dimension d = getPreferredSize();
- w = d.width;
- h = d.height;
- } else {
- final java.awt.Dimension min;
- if(this.isMinimumSizeSet()) {
- min = getMinimumSize();
- } else {
- min = new java.awt.Dimension(0, 0);
- }
- java.awt.Insets ins = cont.getInsets();
- w = Math.max(min.width, cont.getWidth() - ins.left - ins.right);
- h = Math.max(min.height, cont.getHeight() - ins.top - ins.bottom);
- }
- setSize(w, h);
- newtChild.setSize(w, h);
- newtChild.reparentWindow(jawtWindow);
- newtChild.setVisible(true);
- configureNewtChild(true);
- newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
- newtChild.windowRepaint(0, 0, w, h);
-
- // force this AWT Canvas to be focus-able,
- // since this it is completely covered by the newtChild (z-order).
- setFocusable(true);
- } else {
- configureNewtChild(false);
- newtChild.setVisible(false);
- newtChild.reparentWindow(null);
- if(null != jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
- }
- }
}
/**
@@ -430,88 +509,419 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
* <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
* <li> Issues <code>destroy()</code> on the NEWT Child</li>
* <li> Remove reference to the NEWT Child</li>
- * <li> Remove this Canvas from it's parent.</li>
* </ul>
* @see Window#destroy()
*/
public final void destroy() {
- if(null!=newtChild) {
- java.awt.Container cont = AWTMisc.getContainer(this);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.destroy() @ "+currentThreadName());
+ Thread.dumpStack();
+ }
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ @Override
+ public void run() {
+ destroyImpl(false /* removeNotify */, false /* windowClosing */);
+ } } );
+ }
+
+ private final void destroyImpl(boolean removeNotify, boolean windowClosing) {
+ synchronized(sync) {
+ final java.awt.Container cont = AWTMisc.getContainer(this);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont);
+ System.err.println("NewtCanvasAWT.destroyImpl @ "+currentThreadName());
+ System.err.println("NewtCanvasAWT.destroyImpl.0 - isApplet "+isApplet+", isOnAWTEDT "+EventQueue.isDispatchThread()+", skipJAWTDestroy "+skipJAWTDestroy+
+ "; removeNotify "+removeNotify+", windowClosing "+windowClosing+", destroyJAWTPending "+destroyJAWTPending+
+ ", hasJAWT "+(null!=jawtWindow)+", hasNEWT "+(null!=newtChild)+
+ "): nw "+newtWinHandleToHexString(newtChild)+", from "+cont);
}
- configureNewtChild(false);
- if(null!=jawtWindow) {
- NewtFactoryAWT.destroyNativeWindow(jawtWindow);
- jawtWindow=null;
+ if( null !=newtChild ) {
+ detachNewtChild(cont);
+
+ if( !removeNotify ) {
+ final Window cWin = newtChild;
+ final Window dWin = cWin.getDelegatedWindow();
+ newtChild=null;
+ if( windowClosing && dWin instanceof WindowImpl ) {
+ ((WindowImpl)dWin).windowDestroyNotify(true);
+ } else {
+ cWin.destroy();
+ }
+ }
}
- newtChild.setVisible(false);
- newtChild.reparentWindow(null);
- newtChild.destroy();
- newtChild=null;
- if(null!=cont) {
- cont.remove(this);
+ if( ( destroyJAWTPending || removeNotify || windowClosing ) && null!=jawtWindow ) {
+ if( skipJAWTDestroy ) {
+ // Bug 910 - See setSkipJAWTDestroy(boolean)
+ destroyJAWTPending = true;
+ } else {
+ NewtFactoryAWT.destroyNativeWindow(jawtWindow);
+ jawtWindow=null;
+ destroyJAWTPending = false;
+ }
}
}
- }
+ }
@Override
public void paint(Graphics g) {
- awtWindowClosingProtocol.addClosingListenerOneShot();
- if(null!=newtChild) {
- newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+ synchronized(sync) {
+ if( validateComponent(true) && !printActive ) {
+ newtChild.windowRepaint(0, 0, getWidth(), getHeight());
+ }
}
}
@Override
public void update(Graphics g) {
- awtWindowClosingProtocol.addClosingListenerOneShot();
- if(null!=newtChild) {
- newtChild.windowRepaint(0, 0, getWidth(), getHeight());
- }
+ paint(g);
}
- private final void requestFocusNEWTChild() {
- if(null!=newtChild) {
- newtChild.setFocusAction(null);
- if(isOnscreen) {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ @SuppressWarnings("deprecation")
+ @Override
+ public void reshape(int x, int y, int width, int height) {
+ synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
+ synchronized(sync) {
+ super.reshape(x, y, width, height);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
+ }
+ if( validateComponent(true) ) {
+ // newtChild.setSize(width, height);
+ }
}
- newtChild.requestFocus();
- newtChild.setFocusAction(focusAction);
}
}
+ private volatile boolean printActive = false;
+ private GLAnimatorControl printAnimator = null;
+ private GLAutoDrawable printGLAD = null;
+ private AWTTilePainter printAWTTiles = null;
+
+ private final GLAutoDrawable getGLAD() {
+ if( null != newtChild && newtChild instanceof GLAutoDrawable ) {
+ return (GLAutoDrawable)newtChild;
+ }
+ return null;
+ }
+
@Override
- public void requestFocus() {
- super.requestFocus();
- requestFocusNEWTChild();
+ public void setupPrint(double scaleMatX, double scaleMatY, int numSamples, int tileWidth, int tileHeight) {
+ printActive = true;
+ final int componentCount = isOpaque() ? 3 : 4;
+ final TileRenderer printRenderer = new TileRenderer();
+ printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
}
+ private final Runnable setupPrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ synchronized(sync) {
+ if( !validateComponent(true) ) {
+ if(DEBUG) {
+ System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable not valid yet");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ if( !isShowing() ) {
+ if(DEBUG) {
+ System.err.println(currentThreadName()+": Info: NewtCanvasAWT setupPrint - skipped GL render, drawable valid, canvas not showing");
+ }
+ printActive = false;
+ return; // not yet available ..
+ }
+ final GLAutoDrawable glad = getGLAD();
+ if( null == glad ) {
+ if( DEBUG ) {
+ System.err.println("AWT print.setup exit, newtChild not a GLAutoDrawable: "+newtChild);
+ }
+ printActive = false;
+ return;
+ }
+ printAnimator = glad.getAnimator();
+ if( null != printAnimator ) {
+ printAnimator.remove(glad);
+ }
+ printGLAD = glad; // _not_ default, shall be replaced by offscreen GLAD
+ final GLCapabilities caps = (GLCapabilities)glad.getChosenGLCapabilities().cloneMutable();
+ final int printNumSamples = printAWTTiles.getNumSamples(caps);
+ GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
+ final boolean reqNewGLADSamples = printNumSamples != caps.getNumSamples();
+ final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getWidth() ||
+ printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getHeight();
+ final boolean reqNewGLADOnscrn = caps.isOnscreen();
+
+ // It is desired to use a new offscreen GLAD, however Bug 830 forbids this for AA onscreen context.
+ // Bug 830: swapGLContextAndAllGLEventListener and onscreen MSAA w/ NV/GLX
+ final boolean reqNewGLAD = !caps.getSampleBuffers() && ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize );
+ if( DEBUG ) {
+ System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+"], "+
+ ", drawableSize "+printDrawable.getWidth()+"x"+printDrawable.getHeight()+
+ ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
+ ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
+ ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
+ }
+ if( reqNewGLAD ) {
+ caps.setDoubleBuffered(false);
+ caps.setOnscreen(false);
+ if( printNumSamples != caps.getNumSamples() ) {
+ caps.setSampleBuffers(0 < printNumSamples);
+ caps.setNumSamples(printNumSamples);
+ }
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ printGLAD = factory.createOffscreenAutoDrawable(null, caps, null,
+ printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
+ printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad, printGLAD);
+ printDrawable = printGLAD.getDelegatedDrawable();
+ }
+ printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
+ printAWTTiles.renderer.setTileSize(printDrawable.getWidth(), printDrawable.getHeight(), 0);
+ printAWTTiles.renderer.attachAutoDrawable(printGLAD);
+ if( DEBUG ) {
+ System.err.println("AWT print.setup "+printAWTTiles);
+ System.err.println("AWT print.setup AA "+printNumSamples+", "+caps);
+ System.err.println("AWT print.setup printGLAD: "+printGLAD.getWidth()+"x"+printGLAD.getHeight()+", "+printGLAD);
+ System.err.println("AWT print.setup printDraw: "+printDrawable.getWidth()+"x"+printDrawable.getHeight()+", "+printDrawable);
+ }
+ }
+ }
+ };
@Override
- public boolean requestFocus(boolean temporary) {
- final boolean res = super.requestFocus(temporary);
- if(res) {
- requestFocusNEWTChild();
+ public void releasePrint() {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
}
- return res;
+ // sendReshape = false; // clear reshape flag
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
}
+ private final Runnable releasePrintOnEDT = new Runnable() {
+ @Override
+ public void run() {
+ synchronized(sync) {
+ if( DEBUG ) {
+ System.err.println("AWT print.release "+printAWTTiles);
+ }
+ final GLAutoDrawable glad = getGLAD();
+ printAWTTiles.dispose();
+ printAWTTiles= null;
+ if( printGLAD != glad ) {
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, glad);
+ printGLAD.destroy();
+ }
+ printGLAD = null;
+ if( null != printAnimator ) {
+ printAnimator.add(glad);
+ printAnimator = null;
+ }
+ printActive = false;
+ }
+ }
+ };
@Override
- public boolean requestFocusInWindow() {
- final boolean res = super.requestFocusInWindow();
- if(res) {
- requestFocusNEWTChild();
+ public void print(Graphics graphics) {
+ synchronized(sync) {
+ if( !printActive || null == printGLAD ) {
+ throw new IllegalStateException("setupPrint() not called");
+ }
+ if(DEBUG && !EventQueue.isDispatchThread()) {
+ System.err.println(currentThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
+ // we cannot dispatch print on AWT-EDT due to printing internal locking ..
+ }
+
+ final Graphics2D g2d = (Graphics2D)graphics;
+ try {
+ printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
+ final TileRenderer tileRenderer = printAWTTiles.renderer;
+ if( DEBUG ) {
+ System.err.println("AWT print.0: "+tileRenderer);
+ }
+ if( !tileRenderer.eot() ) {
+ try {
+ do {
+ tileRenderer.display();
+ } while ( !tileRenderer.eot() );
+ if( DEBUG ) {
+ System.err.println("AWT print.1: "+printAWTTiles);
+ }
+ tileRenderer.reset();
+ } finally {
+ printAWTTiles.resetGraphics2D();
+ }
+ }
+ } catch (NoninvertibleTransformException nte) {
+ System.err.println("Catched: Inversion failed of: "+g2d.getTransform());
+ nte.printStackTrace();
+ }
+ if( DEBUG ) {
+ System.err.println("AWT print.X: "+printAWTTiles);
+ }
}
- return res;
}
- @Override
- public boolean requestFocusInWindow(boolean temporary) {
- final boolean res = super.requestFocusInWindow(temporary);
- if(res) {
- requestFocusNEWTChild();
+ private final boolean validateComponent(boolean attachNewtChild) {
+ if( Beans.isDesignTime() || !isDisplayable() ) {
+ return false;
+ }
+ if ( null == newtChild || null == jawtWindow ) {
+ return false;
+ }
+ if( 0 >= getWidth() || 0 >= getHeight() ) {
+ return false;
+ }
+
+ if( attachNewtChild && !newtChildAttached && null != newtChild ) {
+ attachNewtChild();
+ }
+
+ return true;
+ }
+
+ private final void configureNewtChild(boolean attach) {
+ awtAdapter.clear();
+ awtMouseAdapter.clear();
+ awtKeyAdapter.setConsumeAWTEvent(false);
+ awtMouseAdapter.clear();
+ awtKeyAdapter.setConsumeAWTEvent(false);
+
+ if(null != keyboardFocusManager) {
+ keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener);
+ keyboardFocusManager = null;
}
- return res;
+
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ if(null == jawtWindow.getGraphicsConfiguration()) {
+ throw new InternalError("XXX");
+ }
+ isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ awtAdapter.setDownstream(jawtWindow, newtChild);
+ newtChild.addWindowListener(clearAWTMenusOnNewtFocus);
+ newtChild.setFocusAction(focusAction); // enable AWT focus traversal
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
+ // force this AWT Canvas to be focus-able,
+ // since this it is completely covered by the newtChild (z-order).
+ setFocusable(true);
+ if(isOnscreen) {
+ // onscreen newt child needs to fwd AWT focus
+ newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
+ } else {
+ // offscreen newt child requires AWT to fwd AWT key/mouse event
+ awtMouseAdapter.setDownstream(newtChild);
+ // We cannot consume AWT mouse click, since it would disable focus via mouse click!
+ // awtMouseAdapter.setConsumeAWTEvent(true);
+ awtKeyAdapter.setDownstream(newtChild);
+ // We manually transfer the focus via NEWT KeyListener, hence we can mark AWT keys as consumed!
+ awtKeyAdapter.setConsumeAWTEvent(true);
+ }
+ } else {
+ newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ setFocusable(false);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if Key and Mouse input events will be passed through AWT,
+ * otherwise only the {@link #getNEWTChild() NEWT child} will receive them.
+ * <p>
+ * Normally only the {@link #getNEWTChild() NEWT child} will receive Key and Mouse input events.
+ * In offscreen mode, e.g. OSX/CALayer, the AWT events will be received and translated into NEWT events
+ * and delivered to the NEWT child window.<br/>
+ * Note: AWT key events will {@link java.awt.event.InputEvent#consume() consumed} in pass-through mode.
+ * </p>
+ */
+ public final boolean isAWTEventPassThrough() {
+ return !isOnscreen;
+ }
+
+ private final void attachNewtChild() {
+ if( null == newtChild || null == jawtWindow || newtChildAttached ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.attachNewtChild.0 @ "+currentThreadName());
+ System.err.println("\twin "+newtWinHandleToHexString(newtChild)+
+ ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+ ", cont "+AWTMisc.getContainer(this));
+ }
+
+ newtChildAttached = true;
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.1: newtChild: "+newtChild);
+ }
+ final int w = getWidth();
+ final int h = getHeight();
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h);
+ }
+ newtChild.setVisible(false);
+ newtChild.setSize(w, h);
+ newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ newtChild.addSurfaceUpdatedListener(jawtWindow);
+ if( jawtWindow.isOffscreenLayerSurfaceEnabled() &&
+ 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
+ AWTEDTExecutor.singleton.invoke(false, forceRelayout);
+ }
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+ }
+ }
+ private final Runnable forceRelayout = new Runnable() {
+ @Override
+ public void run() {
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.forceRelayout.0");
+ }
+ // Hack to force proper native AWT layout incl. CALayer components on OSX
+ final java.awt.Component component = NewtCanvasAWT.this;
+ final int cW = component.getWidth();
+ final int cH = component.getHeight();
+ component.setSize(cW+1, cH+1);
+ component.setSize(cW, cH);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.forceRelayout.X");
+ }
+ } };
+
+ private final void detachNewtChild(java.awt.Container cont) {
+ if( null == newtChild || null == jawtWindow || !newtChildAttached ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ // if ( isShowing() == false ) -> Container was not visible yet.
+ // if ( isShowing() == true ) -> Container is already visible.
+ System.err.println("NewtCanvasAWT.detachNewtChild.0: win "+newtWinHandleToHexString(newtChild)+
+ ", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ", comp "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+
+ ", cont "+cont);
+ }
+
+ newtChild.removeSurfaceUpdatedListener(jawtWindow);
+ newtChildAttached = false;
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+
+ newtChild.reparentWindow(null, -1, -1, 0 /* hint */); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
+
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
+ }
}
// Disables the AWT's erasing of this Canvas's background on Windows
@@ -525,6 +935,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
if (!disableBackgroundEraseInitialized) {
try {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
Class<?> clazz = getToolkit().getClass();
@@ -563,5 +974,14 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
}
}
+
+ protected static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
index d06aca039..9cecca9c5 100755..100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -32,6 +32,7 @@ import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Container;
+import java.awt.EventQueue;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
@@ -42,15 +43,19 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.jawt.JAWTUtil;
+
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.util.applet.JOGLNewtAppletBase;
-/**
+/**
* Simple GLEventListener deployment as an applet using JOGL. This demo must be
* referenced from a web page via an &lt;applet&gt; tag.
- *
+ *
* <p>
- * Example of an applet tag using GearsES2 within the applet area (normal case):
+ * Example of an applet tag using GearsES2 within the applet area (normal case):
* <pre>
&lt;applet width=100 height=100&gt;
&lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
@@ -63,9 +68,9 @@ import com.jogamp.newt.opengl.GLWindow;
&lt;/applet&gt;Hello Gears !
* </pre>
* </p>
- *
+ *
* <p>
- * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
+ * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
* <pre>
&lt;applet width=1 height=1&gt;
&lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
@@ -93,22 +98,22 @@ import com.jogamp.newt.opengl.GLWindow;
@SuppressWarnings("serial")
public class JOGLNewtApplet1Run extends Applet {
public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
-
- GLWindow glWindow;
- NewtCanvasAWT newtCanvasAWT;
- JOGLNewtAppletBase base;
+
+ GLWindow glWindow = null;
+ NewtCanvasAWT newtCanvasAWT = null;
+ JOGLNewtAppletBase base = null;
/** if valid glStandalone:=true (own window) ! */
- int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
- boolean glStandalone = false;
+ int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
+ @Override
public void init() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.init() START");
+ System.err.println("JOGLNewtApplet1Run.init() START - "+currentThreadName());
}
if(!(this instanceof Container)) {
throw new RuntimeException("This Applet is not a AWT Container");
}
- Container container = (Container) this;
+ final Container container = this;
String glEventListenerClazzName=null;
String glProfileName=null;
@@ -134,7 +139,7 @@ public class JOGLNewtApplet1Run extends Applet {
glCloseable = JOGLNewtAppletBase.str2Bool(getParameter("gl_closeable"), glCloseable);
glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
glAlphaBits = JOGLNewtAppletBase.str2Int(getParameter("gl_alpha"), glAlphaBits);
- glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
+ glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
glXd = JOGLNewtAppletBase.str2Int(getParameter("gl_dx"), glXd);
glYd = JOGLNewtAppletBase.str2Int(getParameter("gl_dy"), glYd);
glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth);
@@ -147,7 +152,7 @@ public class JOGLNewtApplet1Run extends Applet {
if(null==glEventListenerClazzName) {
throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
}
- glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+ final boolean glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
if(DEBUG) {
System.err.println("JOGLNewtApplet1Run Configuration:");
System.err.println("glStandalone: "+glStandalone);
@@ -167,8 +172,8 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("glNumMultisampleBuffer: "+glNumMultisampleBuffer);
System.err.println("glNoDefaultKeyListener: "+glNoDefaultKeyListener);
}
-
- base = new JOGLNewtAppletBase(glEventListenerClazzName,
+
+ base = new JOGLNewtAppletBase(glEventListenerClazzName,
glSwapInterval,
glNoDefaultKeyListener,
glCloseable,
@@ -190,10 +195,13 @@ public class JOGLNewtApplet1Run extends Applet {
glWindow.setDefaultCloseOperation(glCloseable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE);
container.setLayout(new BorderLayout());
if(appletDebugTestBorder) {
- container.add(new Button("North"), BorderLayout.NORTH);
- container.add(new Button("South"), BorderLayout.SOUTH);
- container.add(new Button("East"), BorderLayout.EAST);
- container.add(new Button("West"), BorderLayout.WEST);
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ container.add(new Button("North"), BorderLayout.NORTH);
+ container.add(new Button("South"), BorderLayout.SOUTH);
+ container.add(new Button("East"), BorderLayout.EAST);
+ container.add(new Button("West"), BorderLayout.WEST);
+ } } );
}
base.init(glWindow);
if(base.isValid()) {
@@ -209,32 +217,45 @@ public class JOGLNewtApplet1Run extends Applet {
addKeyListener((KeyListener)glEventListener);
}
}
- if(glStandalone) {
- newtCanvasAWT = null;
- } else {
- newtCanvasAWT = new NewtCanvasAWT(glWindow);
- container.add(newtCanvasAWT, BorderLayout.CENTER);
- container.validate();
+ if( !glStandalone ) {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ newtCanvasAWT = new NewtCanvasAWT(glWindow);
+ newtCanvasAWT.setSkipJAWTDestroy(true); // Bug 910
+ container.add(newtCanvasAWT, BorderLayout.CENTER);
+ container.validate();
+ } } );
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.init() END");
+ System.err.println("JOGLNewtApplet1Run.init() END - "+currentThreadName());
}
}
+ private static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
+
+ @Override
public void start() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.start() START");
+ System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+") - "+currentThreadName());
}
- this.validate();
- this.setVisible(true);
-
- final java.awt.Point p0 = this.getLocationOnScreen();
- if(glStandalone) {
+ final java.awt.Point[] p0 = { null };
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ setVisible(true);
+ p0[0] = getLocationOnScreen();
+ if( null != newtCanvasAWT ) {
+ newtCanvasAWT.setFocusable(true);
+ newtCanvasAWT.requestFocus();
+ }
+ }
+ });
+ if( null == newtCanvasAWT ) {
+ glWindow.requestFocus();
glWindow.setSize(glWidth, glHeight);
- glWindow.setPosition(p0.x+glXd, p0.y+glYd);
+ glWindow.setPosition(p0[0].x+glXd, p0[0].y+glYd);
}
if(DEBUG) {
Component topC = this;
@@ -251,34 +272,54 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("GLWindow: "+glWindow);
}
base.start();
+ if( null != newtCanvasAWT &&
+ newtCanvasAWT.isOffscreenLayerSurfaceEnabled() &&
+ 0 != ( JAWTUtil.JAWT_OSX_CALAYER_QUIRK_POSITION & JAWTUtil.getOSXCALayerQuirks() ) ) {
+ // force relayout
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ final int cW = newtCanvasAWT.getWidth();
+ final int cH = newtCanvasAWT.getHeight();
+ newtCanvasAWT.setSize(cW+1, cH+1);
+ newtCanvasAWT.setSize(cW, cH);
+ } } );
+ }
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.start() END");
+ System.err.println("JOGLNewtApplet1Run.start() END - "+currentThreadName());
}
}
+ @Override
public void stop() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.stop() START");
+ System.err.println("JOGLNewtApplet1Run.stop() START - "+currentThreadName());
}
base.stop();
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.stop() END");
+ System.err.println("JOGLNewtApplet1Run.stop() END - "+currentThreadName());
}
}
+ @Override
public void destroy() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.destroy() START");
- }
- glWindow.setVisible(false); // hide 1st
- if(!glStandalone) {
- glWindow.reparentWindow(null); // get out of newtCanvasAWT
- this.remove(newtCanvasAWT); // remove newtCanvasAWT
+ System.err.println("JOGLNewtApplet1Run.destroy() START - "+currentThreadName());
}
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ public void run() {
+ glWindow.setVisible(false); // hide 1st
+ if( null != newtCanvasAWT ) {
+ newtCanvasAWT.setSkipJAWTDestroy(false); // Bug 910
+ remove(newtCanvasAWT); // remove newtCanvasAWT incl. glWindow.reparentWindow(null) if not done yet!
+ newtCanvasAWT.destroy();
+ }
+ } } );
base.destroy(); // destroy glWindow unrecoverable
base=null;
+ glWindow=null;
+ newtCanvasAWT=null;
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.destroy() END");
+ System.err.println("JOGLNewtApplet1Run.destroy() END - "+currentThreadName());
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java b/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java
new file mode 100644
index 000000000..edb2429bb
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/DoubleTapScrollGesture.java
@@ -0,0 +1,347 @@
+/**
+ * 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 com.jogamp.newt.event;
+
+import jogamp.newt.Debug;
+
+/**
+ * 2 pointer scroll/rotate gesture handler processing {@link MouseEvent}s
+ * while producing {@link MouseEvent#EVENT_MOUSE_WHEEL_MOVED} events if gesture is completed.
+ * <p>
+ * Criteria related to parameters:
+ * <pre>
+ * - doubleTapSlop (scaled in pixels):
+ * - Max 2 finger distance to start 'scroll' mode
+ * - Max. distance diff of current 2-pointer middle and initiated 2-pointer middle.
+ *
+ * - touchSlop (scaled in pixels):
+ * - Min. movement w/ 2 pointer within ScaledDoubleTapSlop starting 'scroll' mode
+ *
+ * - Avoid computation if not within gesture, especially for MOVE/DRAG
+ *
+ * - Only allow gesture to start with PRESS
+ *
+ * - Leave gesture completely with RELEASE of both/all fingers, or dist-diff exceeds doubleTapSlop
+ *
+ * - Tolerate temporary lift 1 of 2 pointer
+ *
+ * - Always validate pointer-id
+ * </pre>
+ * </p>
+ * Implementation uses a n-state to get detect gesture:
+ * <p>
+ * <table border="1">
+ * <tr><th>from</th> <th>to</th> <th>action</th></tr>
+ * <tr><td>NONE</td> <td>1PRESS</td> <td>1-pointer-pressed</td></tr>
+ * <tr><td>1PRESS</td> <td>2PRESS_T</td> <td>2-pointer-pressed within doubleTapSlope</td></tr>
+ * <tr><td>2PRESS_T</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop and scrollLen >= scrollSlop</td></tr>
+ * <tr><td>2PRESS_C</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop</td></tr>
+ * <tr><td>SCROLL</td> <td>SCROLL</td> <td>2-pointer dragged, dist-diff within doubleTapSlop</td></tr>
+ * </table>
+ * State ST_2PRESS_C merely exist to pick up gesture after one pointer has been lost temporarily.
+ * </p>
+ * <p>
+ * {@link #isWithinGesture()} returns gestureState >= 2PRESS_C
+ * </p>
+ */
+public class DoubleTapScrollGesture implements GestureHandler {
+ /** Scroll threshold in pixels (fallback), defaults to 16 pixels. Can be overriden by integer property <code>newt.event.scroll_slop_pixel</code>.*/
+ public static final int SCROLL_SLOP_PIXEL;
+ /** Two pointer 'double tap' slop in pixels (fallback), defaults to 104 pixels. Can be overriden by integer property <code>newt.event.double_tap_slop_pixel</code>.*/
+ public static final int DOUBLE_TAP_SLOP_PIXEL;
+
+ /** Scroll threshold in millimeter, defaults to 3 mm. Can be overriden by integer property <code>newt.event.scroll_slop_mm</code>.*/
+ public static final float SCROLL_SLOP_MM;
+ /** Two pointer 'double tap' slop in millimeter, defaults to 20 mm. Can be overriden by integer property <code>newt.event.double_tap_slop_mm</code>.*/
+ public static final float DOUBLE_TAP_SLOP_MM;
+
+ static {
+ Debug.initSingleton();
+
+ SCROLL_SLOP_PIXEL = Debug.getIntProperty("newt.event.scroll_slop_pixel", true, 16);
+ DOUBLE_TAP_SLOP_PIXEL = Debug.getIntProperty("newt.event.double_tap_slop_pixel", true, 104);
+ SCROLL_SLOP_MM = Debug.getIntProperty("newt.event.scroll_slop_mm", true, 3);
+ DOUBLE_TAP_SLOP_MM = Debug.getIntProperty("newt.event.double_tap_slop_mm", true, 20);
+ }
+
+ private static final int ST_NONE = 0;
+ private static final int ST_1PRESS = 1;
+ private static final int ST_2PRESS_T = 2;
+ private static final int ST_2PRESS_C = 3;
+ private static final int ST_SCROLL = 4;
+
+ private final int scrollSlop, scrollSlopSquare, doubleTapSlop, doubleTapSlopSquare;
+ private final float[] scrollDistance = new float[] { 0f, 0f };
+ private int[] pIds = new int[] { -1, -1 };
+ /** See class docu */
+ private int gestureState;
+ private int sqStartDist;
+ private int lastX, lastY;
+ private int pointerDownCount;
+ private MouseEvent hitGestureEvent;
+
+ private static final int getSquareDistance(float x1, float y1, float x2, float y2) {
+ final int deltaX = (int) x1 - (int) x2;
+ final int deltaY = (int) y1 - (int) y2;
+ return deltaX * deltaX + deltaY * deltaY;
+ }
+
+ private int gesturePointers(final MouseEvent e, final int excludeIndex) {
+ int j = 0;
+ for(int i=e.getPointerCount()-1; i>=0; i--) {
+ if( excludeIndex != i ) {
+ final int id = e.getPointerId(i);
+ if( pIds[0] == id || pIds[1] == id ) {
+ j++;
+ }
+ }
+ }
+ return j;
+ }
+
+ /**
+ * scaledScrollSlop < scaledDoubleTapSlop
+ * @param scaledScrollSlop Distance a pointer can wander before we think the user is scrolling in <i>pixels</i>.
+ * @param scaledDoubleTapSlop Distance in <i>pixels</i> between the first touch and second touch to still be considered a double tap.
+ */
+ public DoubleTapScrollGesture(int scaledScrollSlop, int scaledDoubleTapSlop) {
+ scrollSlop = scaledScrollSlop;
+ scrollSlopSquare = scaledScrollSlop * scaledScrollSlop;
+ doubleTapSlop = scaledDoubleTapSlop;
+ doubleTapSlopSquare = scaledDoubleTapSlop * scaledDoubleTapSlop;
+ pointerDownCount = 0;
+ clear(true);
+ if(DEBUG) {
+ System.err.println("DoubleTapScroll scrollSlop (scaled) "+scrollSlop);
+ System.err.println("DoubleTapScroll doubleTapSlop (scaled) "+doubleTapSlop);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DoubleTapScroll[state "+gestureState+", in "+isWithinGesture()+", has "+(null!=hitGestureEvent)+", pc "+pointerDownCount+"]";
+ }
+
+ @Override
+ public void clear(boolean clearStarted) {
+ scrollDistance[0] = 0f;
+ scrollDistance[1] = 0f;
+ hitGestureEvent = null;
+ if( clearStarted ) {
+ gestureState = ST_NONE;
+ sqStartDist = 0;
+ pIds[0] = -1;
+ pIds[1] = -1;
+ lastX = 0;
+ lastY = 0;
+ }
+ }
+
+ @Override
+ public boolean isWithinGesture() {
+ return ST_2PRESS_C <= gestureState;
+ }
+
+ @Override
+ public boolean hasGesture() {
+ return null != hitGestureEvent;
+ }
+
+ @Override
+ public InputEvent getGestureEvent() {
+ if( null != hitGestureEvent ) {
+ final MouseEvent ge = hitGestureEvent;
+ int modifiers = ge.getModifiers();
+ final float[] rotationXYZ = ge.getRotation();
+ rotationXYZ[0] = scrollDistance[0] / scrollSlop;
+ rotationXYZ[1] = scrollDistance[1] / scrollSlop;
+ if( rotationXYZ[0]*rotationXYZ[0] > rotationXYZ[1]*rotationXYZ[1] ) {
+ // Horizontal scroll -> SHIFT
+ modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ }
+ return new MouseEvent(MouseEvent.EVENT_MOUSE_WHEEL_MOVED, ge.getSource(), ge.getWhen(), modifiers,
+ ge.getAllPointerTypes(), ge.getAllPointerIDs(),
+ ge.getAllX(), ge.getAllY(), ge.getAllPressures(), ge.getMaxPressure(),
+ ge.getButton(), ge.getClickCount(), rotationXYZ, scrollSlop);
+ }
+ return null;
+ }
+
+ public final float[] getScrollDistanceXY() {
+ return scrollDistance;
+ }
+
+ @Override
+ public boolean process(final InputEvent in) {
+ if( null != hitGestureEvent || !(in instanceof MouseEvent) ) {
+ return true;
+ }
+ final MouseEvent pe = (MouseEvent)in;
+ if( pe.getPointerType(0).getPointerClass() != MouseEvent.PointerClass.Onscreen ) {
+ return false;
+ }
+ pointerDownCount = pe.getPointerCount();
+ final int eventType = pe.getEventType();
+ final int x0 = pe.getX(0);
+ final int y0 = pe.getY(0);
+ switch ( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED: {
+ int gPtr = 0;
+ if( ST_NONE == gestureState && 1 == pointerDownCount ) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = -1;
+ gestureState = ST_1PRESS;
+ } else if( ST_NONE < gestureState && 2 == pointerDownCount && 1 == gesturePointers(pe, 0) /* w/o pressed pointer */ ) {
+ final int x1 = pe.getX(1);
+ final int y1 = pe.getY(1);
+ final int xm = (x0+x1)/2;
+ final int ym = (y0+y1)/2;
+
+ if( ST_1PRESS == gestureState ) {
+ final int sqDist = getSquareDistance(x0, y0, x1, y1);
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ if( isDistWithinDoubleTapSlop ) {
+ // very first 2-finger touch-down
+ gPtr = 2;
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = pe.getPointerId(1);
+ lastX = xm;
+ lastY = ym;
+ sqStartDist = sqDist;
+ gestureState = ST_2PRESS_T;
+ }
+ if(DEBUG) {
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ System.err.println(this+".pressed.1: dist "+dist+", gPtr "+gPtr+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", last "+lastX+"/"+lastY+", "+pe);
+ }
+ } else if( ST_2PRESS_C == gestureState ) { // pick up gesture after temp loosing one pointer
+ gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers re-touch-down
+ lastX = xm;
+ lastY = ym;
+ } else {
+ // other 2 pointers .. should rarely happen!
+ clear(true);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println(this+".pressed: gPtr "+gPtr+", this "+lastX+"/"+lastY+", "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_RELEASED: {
+ pointerDownCount--; // lifted
+ final int gPtr = gesturePointers(pe, 0); // w/o lifted pointer
+ if ( 1 == gPtr ) {
+ // tolerate lifting 1 of 2 gesture pointers temporary
+ gestureState = ST_2PRESS_C;
+ } else if( 0 == gPtr ) {
+ // all lifted
+ clear(true);
+ }
+ if(DEBUG) {
+ System.err.println(this+".released: gPtr "+gPtr+", "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_DRAGGED: {
+ if( 2 == pointerDownCount && ST_1PRESS < gestureState ) {
+ final int gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers
+ final int x1 = pe.getX(1);
+ final int y1 = pe.getY(1);
+ final int xm = (x0+x1)/2;
+ final int ym = (y0+y1)/2;
+ final int sqDist = getSquareDistance(x0, y0, x1, y1);
+ final boolean isDistDiffWithinDoubleTapSlop = Math.abs(sqDist - sqStartDist) <= doubleTapSlopSquare;
+ if( isDistDiffWithinDoubleTapSlop ) {
+ switch( gestureState ) {
+ case ST_2PRESS_T: {
+ final int sqScrollLen = getSquareDistance(lastX, lastY, xm, ym);
+ if( sqScrollLen > scrollSlopSquare ) { // min. scrolling threshold reached
+ gestureState = ST_SCROLL;
+ }
+ } break;
+
+ case ST_2PRESS_C:
+ gestureState = ST_SCROLL;
+ break;
+
+ case ST_SCROLL:
+ scrollDistance[0] = lastX - xm;
+ scrollDistance[1] = lastY - ym;
+ hitGestureEvent = pe;
+ break;
+ }
+ if(DEBUG) {
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ final int sqScrollLen = getSquareDistance(lastX, lastY, xm, ym);
+ final int scrollLen = (int)Math.round(Math.sqrt(sqScrollLen));
+ System.err.println(this+".dragged.1: pDist "+dist+", scrollLen "+scrollLen+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", diffDistWithinTapSlop "+isDistDiffWithinDoubleTapSlop+
+ ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+
+ ", this "+xm+"/"+ym+", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ } else {
+ // distance too big ..
+ if(DEBUG) {
+ final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare;
+ final int dist = (int)Math.round(Math.sqrt(sqDist));
+ final int startDist = (int)Math.round(Math.sqrt(sqStartDist));
+ System.err.println(this+".dragged.X1: pDist "+dist+", distStart "+startDist+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", diffDistWithinTapSlop "+isDistDiffWithinDoubleTapSlop+
+ ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+
+ ", this "+xm+"/"+ym+", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ clear(true);
+ }
+ if( ST_2PRESS_T < gestureState ) {
+ // state ST_2PRESS_T waits for min scroll threshold !
+ lastX = xm;
+ lastY = ym;
+ }
+ } else {
+ // other 2 pointers .. should rarely happen!
+ if(DEBUG) {
+ System.err.println(this+".dragged.X2: gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+
+ ", last "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]);
+ }
+ clear(true);
+ }
+ }
+ } break;
+
+ default:
+ }
+ return null != hitGestureEvent;
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/GestureHandler.java b/src/newt/classes/com/jogamp/newt/event/GestureHandler.java
new file mode 100644
index 000000000..2e98a8a01
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/GestureHandler.java
@@ -0,0 +1,143 @@
+/**
+ * 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 com.jogamp.newt.event;
+
+import jogamp.newt.Debug;
+
+/**
+ * Generic gesture handler interface designed to allow pass-through
+ * filtering of {@link InputEvent}s.
+ * <p>
+ * To avoid negative impact on event processing,
+ * implementation shall restrict computation as much as possible
+ * and only within it's appropriate gesture states.
+ * </p>
+ * <p>
+ * To allow custom user events, other than the <i>normal</i> {@link InputEvent}s,
+ * a user may return a {@link GestureEvent} in it's implementation.
+ * </p>
+ */
+public interface GestureHandler {
+ public static final boolean DEBUG = Debug.debug("Window.MouseEvent");
+
+ /** A custom gesture event */
+ @SuppressWarnings("serial")
+ public static class GestureEvent extends InputEvent {
+ /** A gesture has been detected. */
+ public static final short EVENT_GESTURE_DETECTED = 400;
+
+ private final GestureHandler handler;
+
+ /**
+ * Creates a gesture event with default type {@link #EVENT_GESTURE_DETECTED}.
+ *
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param handler
+ */
+ public GestureEvent(Object source, long when, int modifiers, GestureHandler handler) {
+ super(EVENT_GESTURE_DETECTED, source, when, modifiers);
+ this.handler = handler;
+ }
+
+ /**
+ * Creates a gesture event with custom <i>event_type</i> !
+ * @param event_type must lie within [400..599]
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param handler
+ */
+ public GestureEvent(short event_type, Object source, long when, int modifiers, GestureHandler handler) {
+ super(event_type, source, when, modifiers);
+ this.handler = handler;
+ }
+
+ /** Return the {@link GestureHandler}, which produced the event. */
+ public final GestureHandler getHandler() { return handler; }
+ }
+
+ /**
+ * Listener for {@link GestureEvent}s.
+ *
+ * @see GestureEvent
+ */
+ public static interface GestureListener extends NEWTEventListener
+ {
+ /** {@link GestureHandler} {@link GestureHandler#hasGesture() has detected} the gesture. */
+ public void gestureDetected(GestureEvent gh);
+ }
+
+ /**
+ * Clears state of handler, i.e. resets all states incl. previous detected gesture.
+ * @param clearStarted if true, also clears {@link #isWithinGesture() started} state,
+ * otherwise stay within gesture - if appropriate.
+ * Staying within a gesture allows fluent continuous gesture sequence,
+ * e.g. for scrolling.
+ */
+ public void clear(boolean clearStarted);
+
+ /**
+ * Returns true if a previous {@link #process(InputEvent)} command produced a gesture,
+ * which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns false.
+ */
+ public boolean hasGesture();
+
+ /**
+ * Returns the corresponding {@link InputEvent} for the gesture as detected by
+ * a previous {@link #process(InputEvent)}, which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns null.
+ * <p>
+ * Only implemented for gestures mapping to {@link InputEvent}s.
+ * </p>
+ */
+ public InputEvent getGestureEvent();
+
+ /**
+ * Returns true if within a gesture as detected by a previous {@link #process(InputEvent)} command,
+ * which has not been {@link #clear(boolean) cleared}.
+ * Otherwise returns false.
+ */
+ public boolean isWithinGesture();
+
+ /**
+ * Process the given {@link InputEvent} and returns true if it produced the gesture.
+ * Otherwise returns false.
+ * <p>
+ * If a gesture was already detected previously and has not been cleared,
+ * method does not process the event and returns true.
+ * </p>
+ * <p>
+ * Besides validation of the event's details,
+ * the handler may also validate the {@link InputEvent.InputClass} and/or {@link InputEvent.InputType}.
+ * </p>
+ */
+ public boolean process(InputEvent e);
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
index 819338ccb..f29b632e8 100644
--- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,102 +29,202 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.common.util.IntBitfield;
+import com.jogamp.newt.Window;
+
@SuppressWarnings("serial")
public abstract class InputEvent extends NEWTEvent
{
- public static final int SHIFT_MASK = 1 << 0;
- public static final int CTRL_MASK = 1 << 1;
- public static final int META_MASK = 1 << 2;
- public static final int ALT_MASK = 1 << 3;
- public static final int ALT_GRAPH_MASK = 1 << 5;
- public static final int BUTTON1_MASK = 1 << 6;
- public static final int BUTTON2_MASK = 1 << 7;
- public static final int BUTTON3_MASK = 1 << 8;
- public static final int BUTTON4_MASK = 1 << 9;
- public static final int BUTTON5_MASK = 1 << 10;
- public static final int BUTTON6_MASK = 1 << 11;
- public static final int CONFINED_MASK = 1 << 16;
- public static final int INVISIBLE_MASK = 1 << 17;
-
- /**
+ /** Interface marking class of input types */
+ public static interface InputClass {
+ }
+
+ /** Interface marking type of input devices */
+ public static interface InputType {
+ }
+
+ public static final int SHIFT_MASK = 1 << 0;
+ public static final int CTRL_MASK = 1 << 1;
+ public static final int META_MASK = 1 << 2;
+ public static final int ALT_MASK = 1 << 3;
+ public static final int ALT_GRAPH_MASK = 1 << 4;
+
+ public static final int BUTTON1_MASK = 1 << 5;
+ public static final int BUTTON2_MASK = 1 << 6;
+ public static final int BUTTON3_MASK = 1 << 7;
+ public static final int BUTTON4_MASK = 1 << 8;
+ public static final int BUTTON5_MASK = 1 << 9;
+ public static final int BUTTON6_MASK = 1 << 10;
+ public static final int BUTTON7_MASK = 1 << 11;
+ public static final int BUTTON8_MASK = 1 << 12;
+ public static final int BUTTON9_MASK = 1 << 13;
+
+ public static final int BUTTONLAST_MASK = 1 << 20; // 16 buttons
+ public static final int BUTTONALL_MASK = 0xffff << 5 ; // 16 buttons
+
+ /** Event is caused by auto-repeat. */
+ public static final int AUTOREPEAT_MASK = 1 << 29;
+
+ /** Pointer is confined, see {@link Window#confinePointer(boolean)}. */
+ public static final int CONFINED_MASK = 1 << 30;
+
+ /** Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */
+ public static final int INVISIBLE_MASK = 1 << 31;
+
+ /**
* Returns the corresponding button mask for the given button.
* <p>
- * In case the given button lies outside
- * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}],
+ * In case the given button lies outside
+ * of the valid range [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON_COUNT}],
* null is returned.
* </p>
*/
public static final int getButtonMask(int button) {
- if( 0 < button && button <= MouseEvent.BUTTON_NUMBER ) {
- return 1 << ( 5 + button ) ;
+ if( 0 < button && button <= MouseEvent.BUTTON_COUNT ) {
+ return 1 << ( 4 + button ) ;
}
return 0;
}
-
- /** Object when attached via {@link #setAttachment(Object)} marks the event consumed,
- * ie. stops propagating the event any further to the event listener.
- */
- public static final Object consumedTag = new Object();
-
- protected InputEvent(int eventType, Object source, long when, int modifiers) {
+
+ protected InputEvent(short eventType, Object source, long when, int modifiers) {
super(eventType, source, when);
this.modifiers=modifiers;
}
+ /** Return the modifier bits of this event, e.g. see {@link #SHIFT_MASK} .. etc. */
public int getModifiers() {
return modifiers;
}
+ /** {@link #getModifiers()} contains {@link #ALT_MASK}. */
public boolean isAltDown() {
return (modifiers&ALT_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #ALT_GRAPH_MASK}. */
public boolean isAltGraphDown() {
return (modifiers&ALT_GRAPH_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #CTRL_MASK}. */
public boolean isControlDown() {
return (modifiers&CTRL_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #META_MASK}. */
public boolean isMetaDown() {
return (modifiers&META_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #SHIFT_MASK}. */
public boolean isShiftDown() {
return (modifiers&SHIFT_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #AUTOREPEAT_MASK}. */
+ public boolean isAutoRepeat() {
+ return (modifiers&AUTOREPEAT_MASK)!=0;
+ }
+ /** {@link #getModifiers()} contains {@link #CONFINED_MASK}. Pointer is confined, see {@link Window#confinePointer(boolean)}. */
public boolean isConfined() {
return (modifiers&CONFINED_MASK)!=0;
}
+ /** {@link #getModifiers()} contains {@link #INVISIBLE_MASK}. Pointer is invisible, see {@link Window#setPointerVisible(boolean)}. */
public boolean isInvisible() {
return (modifiers&INVISIBLE_MASK)!=0;
}
+ public StringBuilder getModifiersString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("[");
+ boolean isFirst = true;
+ if(isShiftDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("shift"); }
+ if(isControlDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("ctrl"); }
+ if(isMetaDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("meta"); }
+ if(isAltDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("alt"); }
+ if(isAltGraphDown()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("altgr"); }
+ if(isAutoRepeat()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("repeat"); }
+ for(int i=1; i<=MouseEvent.BUTTON_COUNT; i++) {
+ if(isButtonDown(i)) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("button").append(i); }
+ }
+ if(isConfined()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("confined"); }
+ if(isInvisible()) { if(!isFirst) { sb.append(", "); } isFirst = false; sb.append("invisible"); }
+ sb.append("]");
+
+ return sb;
+ }
+
/**
- * @return Array of pressed mouse buttons [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}].
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * @return Array of pressed mouse buttons [{@link MouseEvent#BUTTON1} .. {@link MouseEvent#BUTTON6}].
* If none is down, the resulting array is of length 0.
*/
- public final int[] getButtonsDown() {
- int len = 0;
- for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
- if(isButtonDown(i)) { len++; }
- }
-
- int[] res = new int[len];
+ public final short[] getButtonsDown() {
+ final int len = getButtonDownCount();
+
+ final short[] res = new short[len];
int j = 0;
- for(int i=1; i<=MouseEvent.BUTTON_NUMBER; i++) {
- if(isButtonDown(i)) { res[j++] = ( MouseEvent.BUTTON1 - 1 ) + i; }
+ for(int i=1; i<=MouseEvent.BUTTON_COUNT; i++) {
+ if( isButtonDown(i) ) { res[j++] = (short) ( ( MouseEvent.BUTTON1 - 1 ) + i ); }
}
return res;
}
+ /**
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * @param button the button to test
+ * @return true if the given button is down
+ */
public final boolean isButtonDown(int button) {
return ( modifiers & getButtonMask(button) ) != 0;
}
-
+
+ /**
+ * Returns the number of pressed buttons by counting the set bits:
+ * <pre>
+ * getBitCount(modifiers & BUTTONALL_MASK);
+ * </pre>
+ * <p>
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * </p>
+ * @see IntBitfield#getBitCount(int)
+ * @see #BUTTONALL_MASK
+ */
+ public final int getButtonDownCount() {
+ return IntBitfield.getBitCount(modifiers & BUTTONALL_MASK);
+ }
+
+ /**
+ * Returns true if at least one button is pressed, otherwise false:
+ * <pre>
+ * 0 != ( modifiers & BUTTONALL_MASK )
+ * </pre>
+ * <p>
+ * See also {@link MouseEvent}'s section about <i>Multiple-Pointer Events</i>.
+ * </p>
+ * @see IntBitfield#getBitCount(int)
+ * @see #BUTTONALL_MASK
+ */
+ public final boolean isAnyButtonDown() {
+ return 0 != ( modifiers & BUTTONALL_MASK );
+ }
+
+ @Override
public String toString() {
- return "InputEvent[modifiers: 0x"+Integer.toHexString(modifiers)+", "+super.toString()+"]";
+ return toString(null).toString();
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("InputEvent[modifiers: ");
+ getModifiersString(sb);
+ sb.append(", ");
+ super.toString(sb).append("]");
+ return sb;
}
private final int modifiers;
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
index 93c8409b1..5cef734bb 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
@@ -4,14 +4,14 @@
*
* 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
@@ -21,21 +21,21 @@
* 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 com.jogamp.newt.event;
public abstract class KeyAdapter implements KeyListener
{
+ @Override
public void keyPressed(KeyEvent e) {
}
+ @Override
public void keyReleased(KeyEvent e) {
}
- public void keyTyped(KeyEvent e) {
- }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 44fcea49c..49aa4e054 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,712 +29,937 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.common.util.IntBitfield;
+
+/**
+ * <a name="eventDelivery"><h5>KeyEvent Delivery</h5></a>
+ *
+ * Key events are delivered in the following order:
+ * <p>
+ * <table border="0">
+ * <tr><th>#</th><th>Event Type</th> <th>Constraints</th> <th>Notes</th></tr>
+ * <tr><td>1</td><td>{@link #EVENT_KEY_PRESSED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * <tr><td>2</td><td>{@link #EVENT_KEY_RELEASED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * </table>
+ * </p>
+ * In case the native platform does not
+ * deliver keyboard events in the above order or skip events,
+ * the NEWT driver will reorder and inject synthetic events if required.
+ * <p>
+ * Besides regular modifiers like {@link InputEvent#SHIFT_MASK} etc.,
+ * the {@link InputEvent#AUTOREPEAT_MASK} bit is added if repetition is detected, following above constraints.
+ * </p>
+ * <p>
+ * Auto-Repeat shall behave as follow:
+ * <pre>
+ P = pressed, R = released
+ 0 = normal, 1 = auto-repeat
+
+ P(0), [ R(1), P(1), R(1), ..], R(0)
+ * </pre>
+ * The idea is if you mask out auto-repeat in your event listener
+ * you just get one long pressed P/R tuple for {@link #isPrintableKey() printable} and {@link #isActionKey() Action} keys.
+ * </p>
+ * <p>
+ * {@link #isActionKey() Action} keys will produce {@link #EVENT_KEY_PRESSED pressed}
+ * and {@link #EVENT_KEY_RELEASED released} events including {@link #isAutoRepeat() auto-repeat}.
+ * </p>
+ * <p>
+ * {@link #isPrintableKey() Printable} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events.
+ * </p>
+ * <p>
+ * {@link #isModifierKey() Modifier} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events
+ * excluding {@link #isAutoRepeat() auto-repeat}.
+ * They will also influence subsequent event's {@link #getModifiers() modifier} bits while pressed.
+ * </p>
+ *
+ * <a name="unicodeMapping"><h5>Unicode Mapping</h5></a>
+ * <p>
+ * {@link #getKeyChar() Key-chars}, as well as
+ * {@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols}
+ * use the UTF-16 unicode space w/o collision.
+ *
+ * </p>
+ * <p>
+ * Non-{@link #isPrintableKey() printable} {@link #getKeyCode() key-codes} and {@link #getKeySymbol() key-symbols},
+ * i.e. {@link #isModifierKey() modifier-} and {@link #isActionKey() action-}keys,
+ * are mapped to unicode's control and private range and do not collide w/ {@link #isPrintableKey() printable} unicode values
+ * with the following exception.
+ * </p>
+ *
+ * <a name="unicodeCollision"><h5>Unicode Collision</h5></a>
+ * <p>
+ * The following {@link #getKeyCode() Key-code}s and {@link #getKeySymbol() key-symbol}s collide w/ unicode space:<br/>
+ * <table border="1">
+ * <tr><th>unicode range</th> <th>virtual key code</th> <th>unicode character</th></tr>
+ * <tr><td>[0x61 .. 0x78]</td> <td>[{@link #VK_F1}..{@link #VK_F24}]</td> <td>['a'..'x']</td></tr>
+ * </table>
+ * </p>
+ * <p>
+ * Collision was chosen for {@link #getKeyCode() Key-code} and {@link #getKeySymbol() key-symbol} mapping
+ * to allow a minimal code range, i.e. <code>[0..255]</code>.
+ * The reduced code range in turn allows the implementation to utilize fast and small lookup tables,
+ * e.g. to implement a key-press state tracker.
+ * </p>
+ * <pre>
+ * http://www.utf8-chartable.de/unicode-utf8-table.pl
+ * http://www.unicode.org/Public/5.1.0/ucd/PropList.txt
+ * https://en.wikipedia.org/wiki/Mapping_of_Unicode_characters
+ * https://en.wikipedia.org/wiki/Unicode_control_characters
+ * https://en.wikipedia.org/wiki/Private_Use_%28Unicode%29#Private_Use_Areas
+ * </pre>
+ * </p>
+ */
@SuppressWarnings("serial")
public class KeyEvent extends InputEvent
{
- public KeyEvent(int eventType, Object source, long when, int modifiers, int keyCode, char keyChar) {
- super(eventType, source, when, modifiers);
- this.keyCode=keyCode;
- this.keyChar=keyChar;
- }
-
- /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */
- public char getKeyChar() {
- return keyChar;
- }
-
- /** Always valid. */
- public int getKeyCode() {
- return keyCode;
- }
-
- public String toString() {
- return "KeyEvent["+getEventTypeString(getEventType())+
- ", code "+keyCode+"("+toHexString(keyCode)+"), char '"+keyChar+"' ("+toHexString((int)keyChar)+"), isActionKey "+isActionKey()+", "+super.toString()+"]";
- }
-
- public static String getEventTypeString(int type) {
- switch(type) {
- case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
- case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
- case EVENT_KEY_TYPED: return "EVENT_KEY_TYPED";
- default: return "unknown (" + type + ")";
+ private KeyEvent(short eventType, Object source, long when, int modifiers, short keyCode, short keySym, int keySymModMask, char keyChar) {
+ super(eventType, source, when, modifiers | keySymModMask);
+ this.keyCode=keyCode;
+ this.keySym=keySym;
+ this.keyChar=keyChar;
+ { // cache modifier and action flags
+ byte _flags = 0;
+ if( isPrintableKey(keySym, false) && isPrintableKey((short)keyChar, true) ) {
+ _flags |= F_PRINTABLE_MASK;
+ } else {
+ if( 0 != keySymModMask ) {
+ _flags |= F_MODIFIER_MASK;
+ } else {
+ // A = U - ( P + M )
+ _flags |= F_ACTION_MASK;
+ }
+ }
+ flags = _flags;
+
+ //
+ // Validate flags
+ //
+ final int pma_bits = flags & ( F_PRINTABLE_MASK | F_MODIFIER_MASK | F_ACTION_MASK ) ;
+ final int pma_count = IntBitfield.getBitCount(pma_bits);
+ if ( 1 != pma_count ) {
+ throw new InternalError("Key must be either of type printable, modifier or action - but it is of "+pma_count+" types: "+this);
+ }
+ }
}
- }
-
- public boolean isActionKey() {
- switch (keyCode) {
- case VK_HOME:
- case VK_END:
- case VK_PAGE_UP:
- case VK_PAGE_DOWN:
- case VK_UP:
- case VK_DOWN:
- case VK_LEFT:
- case VK_RIGHT:
-
- case VK_F1:
- case VK_F2:
- case VK_F3:
- case VK_F4:
- case VK_F5:
- case VK_F6:
- case VK_F7:
- case VK_F8:
- case VK_F9:
- case VK_F10:
- case VK_F11:
- case VK_F12:
- case VK_F13:
- case VK_F14:
- case VK_F15:
- case VK_F16:
- case VK_F17:
- case VK_F18:
- case VK_F19:
- case VK_F20:
- case VK_F21:
- case VK_F22:
- case VK_F23:
- case VK_F24:
- case VK_PRINTSCREEN:
- case VK_CAPS_LOCK:
- case VK_PAUSE:
- case VK_INSERT:
-
- case VK_HELP:
- case VK_WINDOWS:
- return true;
- }
- return false;
- }
-
- private final int keyCode;
- private final char keyChar;
- public static final int EVENT_KEY_PRESSED = 300;
- public static final int EVENT_KEY_RELEASED= 301;
- public static final int EVENT_KEY_TYPED = 302;
-
- /* Virtual key codes. */
-
- public static final int VK_ENTER = '\n';
- public static final int VK_BACK_SPACE = '\b';
- public static final int VK_TAB = '\t';
- public static final int VK_CANCEL = 0x03;
- public static final int VK_CLEAR = 0x0C;
- public static final int VK_SHIFT = 0x10;
- public static final int VK_CONTROL = 0x11;
- public static final int VK_ALT = 0x12;
- public static final int VK_PAUSE = 0x13;
- public static final int VK_CAPS_LOCK = 0x14;
- public static final int VK_ESCAPE = 0x1B;
- public static final int VK_SPACE = 0x20;
- public static final int VK_PAGE_UP = 0x21;
- public static final int VK_PAGE_DOWN = 0x22;
- public static final int VK_END = 0x23;
- public static final int VK_HOME = 0x24;
+ public static KeyEvent create(short eventType, Object source, long when, int modifiers, short keyCode, short keySym, char keyChar) {
+ return new KeyEvent(eventType, source, when, modifiers, keyCode, keySym, getModifierMask(keySym), keyChar);
+ }
/**
- * Constant for the non-numpad <b>left</b> arrow key.
- * @see #VK_KP_LEFT
+ * Returns the <i>UTF-16</i> character reflecting the {@link #getKeySymbol() key symbol}
+ * incl. active {@link #isModifierKey() modifiers}.
+ * @see #getKeySymbol()
+ * @see #getKeyCode()
*/
- public static final int VK_LEFT = 0x25;
+ public final char getKeyChar() {
+ return keyChar;
+ }
/**
- * Constant for the non-numpad <b>up</b> arrow key.
- * @see #VK_KP_UP
+ * Returns the virtual <i>key symbol</i> reflecting the current <i>keyboard layout</i>.
+ * <p>
+ * For {@link #isPrintableKey() printable keys}, the <i>key symbol</i> is the {@link #isModifierKey() unmodified}
+ * representation of the UTF-16 {@link #getKeyChar() key char}.<br/>
+ * E.g. symbol [{@link #VK_A}, 'A'] for char 'a'.
+ * </p>
+ * @see #isPrintableKey()
+ * @see #getKeyChar()
+ * @see #getKeyCode()
*/
- public static final int VK_UP = 0x26;
+ public final short getKeySymbol() {
+ return keySym;
+ }
/**
- * Constant for the non-numpad <b>right</b> arrow key.
- * @see #VK_KP_RIGHT
- */
- public static final int VK_RIGHT = 0x27;
+ * Returns the virtual <i>key code</i> using a fixed mapping to the <i>US keyboard layout</i>.
+ * <p>
+ * In contrast to {@link #getKeySymbol() key symbol}, <i>key code</i>
+ * uses a fixed <i>US keyboard layout</i> and therefore is keyboard layout independent.
+ * </p>
+ * <p>
+ * E.g. <i>virtual key code</i> {@link #VK_Y} denotes the same physical key
+ * regardless whether <i>keyboard layout</i> <code>QWERTY</code> or
+ * <code>QWERTZ</code> is active. The {@link #getKeySymbol() key symbol} of the former is
+ * {@link #VK_Y}, where the latter produces {@link #VK_Y}.
+ * </p>
+ * @see #getKeyChar()
+ * @see #getKeySymbol()
+ */
+ public final short getKeyCode() {
+ return keyCode;
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("KeyEvent[").append(getEventTypeString(getEventType())).append(", code ").append(toHexString(keyCode)).append(", sym ").append(toHexString(keySym)).append(", char '").append(keyChar).append("' (").append(toHexString((short)keyChar))
+ .append("), printable ").append(isPrintableKey()).append(", modifier ").append(isModifierKey()).append(", action ").append(isActionKey()).append(", ");
+ return super.toString(sb).append("]");
+ }
+
+ public static String getEventTypeString(short type) {
+ switch(type) {
+ case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
+ case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
+ default: return "unknown (" + type + ")";
+ }
+ }
/**
- * Constant for the non-numpad <b>down</b> arrow key.
- * @see #VK_KP_DOWN
+ * @param keyChar UTF16 value to map. It is expected that the incoming keyChar value is unshifted and unmodified,
+ * however, lower case a-z is mapped to {@link KeyEvent#VK_A} - {@link KeyEvent#VK_Z}.
+ * @return {@link KeyEvent} virtual key (VK) value.
*/
- public static final int VK_DOWN = 0x28;
+ public static short utf16ToVKey(char keyChar) {
+ if( 'a' <= keyChar && keyChar <= 'z' ) {
+ return (short) ( ( keyChar - 'a' ) + KeyEvent.VK_A );
+ }
+ return (short) keyChar;
+ }
/**
- * Constant for the comma key, ","
- */
- public static final int VK_COMMA = 0x2C;
+ * Returns <code>true</code> if the given <code>virtualKey</code> represents a modifier key, otherwise <code>false</code>.
+ * <p>
+ * A modifier key is one of {@link #VK_SHIFT}, {@link #VK_CONTROL}, {@link #VK_ALT}, {@link #VK_ALT_GRAPH}, {@link #VK_META}.
+ * </p>
+ */
+ public static boolean isModifierKey(short vKey) {
+ switch (vKey) {
+ case VK_SHIFT:
+ case VK_CONTROL:
+ case VK_ALT:
+ case VK_ALT_GRAPH:
+ case VK_META:
+ return true;
+ default:
+ return false;
+ }
+ }
/**
- * Constant for the minus key, "-"
- * @since 1.2
- */
- public static final int VK_MINUS = 0x2D;
+ * If <code>vKey</code> is a {@link #isModifierKey() modifier key}, method returns the corresponding modifier mask,
+ * otherwise 0.
+ */
+ public static int getModifierMask(short vKey) {
+ switch (vKey) {
+ case VK_SHIFT:
+ return InputEvent.SHIFT_MASK;
+ case VK_CONTROL:
+ return InputEvent.CTRL_MASK;
+ case VK_ALT:
+ case VK_ALT_GRAPH:
+ return InputEvent.ALT_MASK;
+ case VK_META:
+ return InputEvent.META_MASK;
+ }
+ return 0;
+ }
/**
- * Constant for the period key, "."
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a modifier key,
+ * otherwise <code>false</code>.
+ * <p>
+ * See {@link #isModifierKey(short)} for details.
+ * </p>
+ * <p>
+ * Note: Implementation uses a cached value.
+ * </p>
*/
- public static final int VK_PERIOD = 0x2E;
+ public final boolean isModifierKey() {
+ return 0 != ( F_MODIFIER_MASK & flags ) ;
+ }
/**
- * Constant for the forward slash key, "/"
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} represents a non-printable and
+ * non-{@link #isModifierKey(short) modifier} action key, otherwise <code>false</code>.
+ * <p>
+ * Hence it is the set A of all keys U w/o printable P and w/o modifiers M:
+ * <code> A = U - ( P + M ) </code>
+ * </p>
+ * @see #isPrintableKey()
+ * @see #isModifierKey()
*/
- public static final int VK_SLASH = 0x2F;
-
- /** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
- public static final int VK_0 = 0x30;
- public static final int VK_1 = 0x31;
- public static final int VK_2 = 0x32;
- public static final int VK_3 = 0x33;
- public static final int VK_4 = 0x34;
- public static final int VK_5 = 0x35;
- public static final int VK_6 = 0x36;
- public static final int VK_7 = 0x37;
- public static final int VK_8 = 0x38;
- public static final int VK_9 = 0x39;
+ public final boolean isActionKey() {
+ return 0 != ( F_ACTION_MASK & flags ) ;
+ }
/**
- * Constant for the semicolon key, ";"
- */
- public static final int VK_SEMICOLON = 0x3B;
+ * Returns <code>true</code> if given <code>uniChar</code> represents a printable character,
+ * i.e. a value other than {@link #VK_UNDEFINED} and not a control or non-printable private code.
+ * <p>
+ * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+ * </p>
+ * <p>
+ * Otherwise returns <code>false</code>.
+ * </p>
+ * <p>
+ * Distinction of key character and virtual key code is made due to <a href="#unicodeCollision">unicode collision</a>.
+ * </p>
+ *
+ * @param uniChar the UTF-16 unicode value, which maybe a virtual key code or key character.
+ * @param isKeyChar true if <code>uniChar</code> is a key character, otherwise a virtual key code
+ */
+ public static boolean isPrintableKey(final short uniChar, final boolean isKeyChar) {
+ if ( VK_BACK_SPACE == uniChar || VK_TAB == uniChar || VK_ENTER == uniChar ) {
+ return true;
+ }
+ if( !isKeyChar ) {
+ if( ( nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+ ( nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+ ( nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+ ( nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+ return false;
+ }
+ } else {
+ if( ( nonPrintableKeys[0].inclKeyChar && nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
+ ( nonPrintableKeys[1].inclKeyChar && nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
+ ( nonPrintableKeys[2].inclKeyChar && nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+ ( nonPrintableKeys[3].inclKeyChar && nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
+ return false;
+ }
+ }
+ return VK_UNDEFINED != uniChar;
+ }
/**
- * Constant for the equals key, "="
+ * Returns <code>true</code> if {@link #getKeySymbol() key symbol} and {@link #getKeyChar() key char}
+ * represents a printable character, i.e. a value other than {@link #VK_UNDEFINED}
+ * and not a control or non-printable private code.
+ * <p>
+ * A printable character is neither a {@link #isModifierKey(short) modifier key}, nor an {@link #isActionKey(short) action key}.
+ * </p>
+ * <p>
+ * Otherwise returns <code>false</code>.
+ * </p>
*/
- public static final int VK_EQUALS = 0x3D;
-
- /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
- public static final int VK_A = 0x41;
- public static final int VK_B = 0x42;
- public static final int VK_C = 0x43;
- public static final int VK_D = 0x44;
- public static final int VK_E = 0x45;
- public static final int VK_F = 0x46;
- public static final int VK_G = 0x47;
- public static final int VK_H = 0x48;
- public static final int VK_I = 0x49;
- public static final int VK_J = 0x4A;
- public static final int VK_K = 0x4B;
- public static final int VK_L = 0x4C;
- public static final int VK_M = 0x4D;
- public static final int VK_N = 0x4E;
- public static final int VK_O = 0x4F;
- public static final int VK_P = 0x50;
- public static final int VK_Q = 0x51;
- public static final int VK_R = 0x52;
- public static final int VK_S = 0x53;
- public static final int VK_T = 0x54;
- public static final int VK_U = 0x55;
- public static final int VK_V = 0x56;
- public static final int VK_W = 0x57;
- public static final int VK_X = 0x58;
- public static final int VK_Y = 0x59;
- public static final int VK_Z = 0x5A;
+ public final boolean isPrintableKey() {
+ return 0 != ( F_PRINTABLE_MASK & flags ) ;
+ }
+
+ private final short keyCode;
+ private final short keySym;
+ private final char keyChar;
+ private final byte flags;
+ private static final byte F_MODIFIER_MASK = 1 << 0;
+ private static final byte F_ACTION_MASK = 1 << 1;
+ private static final byte F_PRINTABLE_MASK = 1 << 2;
+
+ /** A key has been pressed, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+ public static final short EVENT_KEY_PRESSED = 300;
+ /** A key has been released, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
+ public static final short EVENT_KEY_RELEASED= 301;
/**
- * Constant for the open bracket key, "["
+ * This value, {@code '\0'}, is used to indicate that the keyChar is unknown or not printable.
*/
- public static final int VK_OPEN_BRACKET = 0x5B;
+ public static final char NULL_CHAR = '\0';
+
+ /* Virtual key codes. */
+ public static class NonPrintableRange {
+ /** min. unicode value, inclusive */
+ public short min;
+ /** max. unicode value, inclusive */
+ public short max;
+ /** true if valid for keyChar values as well, otherwise only valid for keyCode and keySym due to collision. */
+ public final boolean inclKeyChar;
+ private NonPrintableRange(short min, short max, boolean inclKeyChar) {
+ this.min = min;
+ this.max = max;
+ this.inclKeyChar = inclKeyChar;
+ }
+ };
/**
- * Constant for the back slash key, "\"
+ * Non printable key ranges, currently fixed to an array of size 4.
+ * <p>
+ * Not included, queried upfront:
+ * <ul>
+ * <li>{@link #VK_BACK_SPACE}</li>
+ * <li>{@link #VK_TAB}</li>
+ * <li>{@link #VK_ENTER}</li>
+ * </ul>
+ * </p>
*/
- public static final int VK_BACK_SLASH = 0x5C;
+ public final static NonPrintableRange[] nonPrintableKeys = {
+ new NonPrintableRange( (short)0x0000, (short)0x001F, true ), // Unicode: Non printable controls: [0x00 - 0x1F], see exclusion above
+ new NonPrintableRange( (short)0x0061, (short)0x0078, false), // Small 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym - Re-used for Fn (collision)
+ new NonPrintableRange( (short)0x008F, (short)0x009F, true ), // Unicode: Non printable controls: [0x7F - 0x9F], Numpad keys [0x7F - 0x8E] are printable!
+ new NonPrintableRange( (short)0xE000, (short)0xF8FF, true ) // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+ };
+
+ //
+ // Unicode: Non printable controls: [0x00 - 0x1F]
+ //
/**
- * Constant for the close bracket key, "]"
- */
- public static final int VK_CLOSE_BRACKET = 0x5D;
-
- public static final int VK_NUMPAD0 = 0x60;
- public static final int VK_NUMPAD1 = 0x61;
- public static final int VK_NUMPAD2 = 0x62;
- public static final int VK_NUMPAD3 = 0x63;
- public static final int VK_NUMPAD4 = 0x64;
- public static final int VK_NUMPAD5 = 0x65;
- public static final int VK_NUMPAD6 = 0x66;
- public static final int VK_NUMPAD7 = 0x67;
- public static final int VK_NUMPAD8 = 0x68;
- public static final int VK_NUMPAD9 = 0x69;
- public static final int VK_MULTIPLY = 0x6A;
- public static final int VK_ADD = 0x6B;
-
- /**
- * This constant is obsolete, and is included only for backwards
- * compatibility.
- * @see #VK_SEPARATOR
+ * This value, {@value}, is used to indicate that the keyCode is unknown.
*/
- public static final int VK_SEPARATER = 0x6C;
+ public static final short VK_UNDEFINED = (short) 0x0;
- /**
- * Constant for the Numpad Separator key.
- * @since 1.4
- */
- public static final int VK_SEPARATOR = VK_SEPARATER;
+ static final short VK_FREE01 = (short) 0x01;
- public static final int VK_SUBTRACT = 0x6D;
- public static final int VK_DECIMAL = 0x6E;
- public static final int VK_DIVIDE = 0x6F;
- public static final int VK_DELETE = 0x7F; /* ASCII DEL */
- public static final int VK_NUM_LOCK = 0x90;
- public static final int VK_SCROLL_LOCK = 0x91;
+ /** Constant for the HOME function key. ASCII: Start Of Text. */
+ public static final short VK_HOME = (short) 0x02;
- /** Constant for the F1 function key. */
- public static final int VK_F1 = 0x70;
+ /** Constant for the END function key. ASCII: End Of Text. */
+ public static final short VK_END = (short) 0x03;
- /** Constant for the F2 function key. */
- public static final int VK_F2 = 0x71;
+ /** Constant for the END function key. ASCII: End Of Transmission. */
+ public static final short VK_FINAL = (short) 0x04;
- /** Constant for the F3 function key. */
- public static final int VK_F3 = 0x72;
+ /** Constant for the PRINT function key. ASCII: Enquiry. */
+ public static final short VK_PRINTSCREEN = (short) 0x05;
- /** Constant for the F4 function key. */
- public static final int VK_F4 = 0x73;
+ static final short VK_FREE06 = (short) 0x06;
+ static final short VK_FREE07 = (short) 0x07;
- /** Constant for the F5 function key. */
- public static final int VK_F5 = 0x74;
+ /** Constant for the BACK SPACE key "\b", matching ASCII. Printable! */
+ public static final short VK_BACK_SPACE = (short) 0x08;
- /** Constant for the F6 function key. */
- public static final int VK_F6 = 0x75;
+ /** Constant for the HORIZ TAB key "\t", matching ASCII. Printable! */
+ public static final short VK_TAB = (short) 0x09;
- /** Constant for the F7 function key. */
- public static final int VK_F7 = 0x76;
+ /** LINE_FEED "\n", matching ASCII, n/a on keyboard. */
+ static final short VK_FREE0A = (short) 0x0A;
- /** Constant for the F8 function key. */
- public static final int VK_F8 = 0x77;
+ /** Constant for the PAGE DOWN function key. ASCII: Vertical Tabulation. */
+ public static final short VK_PAGE_DOWN = (short) 0x0B;
- /** Constant for the F9 function key. */
- public static final int VK_F9 = 0x78;
+ /** Constant for the CLEAR key, i.e. FORM FEED, matching ASCII. */
+ public static final short VK_CLEAR = (short) 0x0C;
- /** Constant for the F10 function key. */
- public static final int VK_F10 = 0x79;
+ /** Constant for the ENTER key, i.e. CARRIAGE RETURN, matching ASCII. Printable! */
+ public static final short VK_ENTER = (short) 0x0D;
- /** Constant for the F11 function key. */
- public static final int VK_F11 = 0x7A;
+ static final short VK_FREE0E = (short) 0x0E;
- /** Constant for the F12 function key. */
- public static final int VK_F12 = 0x7B;
+ /** Constant for the CTRL function key. ASCII: shift-in. */
+ public static final short VK_SHIFT = (short) 0x0F;
- /**
- * Constant for the F13 function key.
- * @since 1.2
- */
- /* F13 - F24 are used on IBM 3270 keyboard; use random range for constants. */
- public static final int VK_F13 = 0xF000;
-
- /**
- * Constant for the F14 function key.
- * @since 1.2
- */
- public static final int VK_F14 = 0xF001;
-
- /**
- * Constant for the F15 function key.
- * @since 1.2
- */
- public static final int VK_F15 = 0xF002;
-
- /**
- * Constant for the F16 function key.
- * @since 1.2
- */
- public static final int VK_F16 = 0xF003;
-
- /**
- * Constant for the F17 function key.
- * @since 1.2
- */
- public static final int VK_F17 = 0xF004;
-
- /**
- * Constant for the F18 function key.
- * @since 1.2
- */
- public static final int VK_F18 = 0xF005;
-
- /**
- * Constant for the F19 function key.
- * @since 1.2
- */
- public static final int VK_F19 = 0xF006;
-
- /**
- * Constant for the F20 function key.
- * @since 1.2
- */
- public static final int VK_F20 = 0xF007;
-
- /**
- * Constant for the F21 function key.
- * @since 1.2
- */
- public static final int VK_F21 = 0xF008;
-
- /**
- * Constant for the F22 function key.
- * @since 1.2
- */
- public static final int VK_F22 = 0xF009;
-
- /**
- * Constant for the F23 function key.
- * @since 1.2
- */
- public static final int VK_F23 = 0xF00A;
-
- /**
- * Constant for the F24 function key.
- * @since 1.2
- */
- public static final int VK_F24 = 0xF00B;
-
- public static final int VK_PRINTSCREEN = 0x9A;
- public static final int VK_INSERT = 0x9B;
- public static final int VK_HELP = 0x9C;
- public static final int VK_META = 0x9D;
+ /** Constant for the PAGE UP function key. ASCII: Data Link Escape. */
+ public static final short VK_PAGE_UP = (short) 0x10;
- public static final int VK_BACK_QUOTE = 0xC0;
- public static final int VK_QUOTE = 0xDE;
+ /** Constant for the CTRL function key. ASCII: device-ctrl-one. */
+ public static final short VK_CONTROL = (short) 0x11;
- /**
- * Constant for the numeric keypad <b>up</b> arrow key.
- * @see #VK_UP
- * @since 1.2
- */
- public static final int VK_KP_UP = 0xE0;
+ /** Constant for the left ALT function key. ASCII: device-ctrl-two. */
+ public static final short VK_ALT = (short) 0x12;
- /**
- * Constant for the numeric keypad <b>down</b> arrow key.
- * @see #VK_DOWN
- * @since 1.2
- */
- public static final int VK_KP_DOWN = 0xE1;
+ /** Constant for the ALT_GRAPH function key, i.e. right ALT key. ASCII: device-ctrl-three. */
+ public static final short VK_ALT_GRAPH = (short) 0x13;
- /**
- * Constant for the numeric keypad <b>left</b> arrow key.
- * @see #VK_LEFT
- * @since 1.2
- */
- public static final int VK_KP_LEFT = 0xE2;
+ /** Constant for the CAPS LOCK function key. ASCII: device-ctrl-four. */
+ public static final short VK_CAPS_LOCK = (short) 0x14;
- /**
- * Constant for the numeric keypad <b>right</b> arrow key.
- * @see #VK_RIGHT
- * @since 1.2
- */
- public static final int VK_KP_RIGHT = 0xE3;
-
- /* For European keyboards */
- /** @since 1.2 */
- public static final int VK_DEAD_GRAVE = 0x80;
- /** @since 1.2 */
- public static final int VK_DEAD_ACUTE = 0x81;
- /** @since 1.2 */
- public static final int VK_DEAD_CIRCUMFLEX = 0x82;
- /** @since 1.2 */
- public static final int VK_DEAD_TILDE = 0x83;
- /** @since 1.2 */
- public static final int VK_DEAD_MACRON = 0x84;
- /** @since 1.2 */
- public static final int VK_DEAD_BREVE = 0x85;
- /** @since 1.2 */
- public static final int VK_DEAD_ABOVEDOT = 0x86;
- /** @since 1.2 */
- public static final int VK_DEAD_DIAERESIS = 0x87;
- /** @since 1.2 */
- public static final int VK_DEAD_ABOVERING = 0x88;
- /** @since 1.2 */
- public static final int VK_DEAD_DOUBLEACUTE = 0x89;
- /** @since 1.2 */
- public static final int VK_DEAD_CARON = 0x8a;
- /** @since 1.2 */
- public static final int VK_DEAD_CEDILLA = 0x8b;
- /** @since 1.2 */
- public static final int VK_DEAD_OGONEK = 0x8c;
- /** @since 1.2 */
- public static final int VK_DEAD_IOTA = 0x8d;
- /** @since 1.2 */
- public static final int VK_DEAD_VOICED_SOUND = 0x8e;
- /** @since 1.2 */
- public static final int VK_DEAD_SEMIVOICED_SOUND = 0x8f;
-
- /** @since 1.2 */
- public static final int VK_AMPERSAND = 0x96;
- /** @since 1.2 */
- public static final int VK_ASTERISK = 0x97;
- /** @since 1.2 */
- public static final int VK_QUOTEDBL = 0x98;
- /** @since 1.2 */
- public static final int VK_LESS = 0x99;
-
- /** @since 1.2 */
- public static final int VK_GREATER = 0xa0;
- /** @since 1.2 */
- public static final int VK_BRACELEFT = 0xa1;
- /** @since 1.2 */
- public static final int VK_BRACERIGHT = 0xa2;
+ static final short VK_FREE15 = (short) 0x15;
+
+ /** Constant for the PAUSE function key. ASCII: sync-idle. */
+ public static final short VK_PAUSE = (short) 0x16;
+
+ /** <b>scroll lock</b> key. ASCII: End Of Transmission Block. */
+ public static final short VK_SCROLL_LOCK = (short) 0x17;
+
+ /** Constant for the CANCEL function key. ASCII: Cancel. */
+ public static final short VK_CANCEL = (short) 0x18;
+
+ static final short VK_FREE19 = (short) 0x19;
+
+ /** Constant for the INSERT function key. ASCII: Substitute. */
+ public static final short VK_INSERT = (short) 0x1A;
+
+ /** Constant for the ESCAPE function key. ASCII: Escape. */
+ public static final short VK_ESCAPE = (short) 0x1B;
+
+ /** Constant for the Convert function key, Japanese "henkan". ASCII: File Separator. */
+ public static final short VK_CONVERT = (short) 0x1C;
+
+ /** Constant for the Don't Convert function key, Japanese "muhenkan". ASCII: Group Separator.*/
+ public static final short VK_NONCONVERT = (short) 0x1D;
+
+ /** Constant for the Accept or Commit function key, Japanese "kakutei". ASCII: Record Separator.*/
+ public static final short VK_ACCEPT = (short) 0x1E;
+
+ /** Constant for the Mode Change (?). ASCII: Unit Separator.*/
+ public static final short VK_MODECHANGE = (short) 0x1F;
+
+ //
+ // Unicode: Printable [0x20 - 0x7E]
+ // NOTE: Collision of 'a' - 'x' [0x61 .. 0x78], used for keyCode/keySym Fn function keys
+ //
+
+ /** Constant for the SPACE function key. ASCII: SPACE. */
+ public static final short VK_SPACE = (short) 0x20;
+
+ /** Constant for the "!" key. */
+ public static final short VK_EXCLAMATION_MARK = (short) 0x21;
+
+ /** Constant for the """ key. */
+ public static final short VK_QUOTEDBL = (short) 0x22;
+
+ /** Constant for the "#" key. */
+ public static final short VK_NUMBER_SIGN = (short) 0x23;
+
+ /** Constant for the "$" key. */
+ public static final short VK_DOLLAR = (short) 0x24;
+
+ /** Constant for the "%" key. */
+ public static final short VK_PERCENT = (short) 0x25;
+
+ /** Constant for the "&" key. */
+ public static final short VK_AMPERSAND = (short) 0x26;
+
+ /** Constant for the "'" key. */
+ public static final short VK_QUOTE = (short) 0x27;
+
+ /** Constant for the "(" key. */
+ public static final short VK_LEFT_PARENTHESIS = (short) 0x28;
+
+ /** Constant for the ")" key. */
+ public static final short VK_RIGHT_PARENTHESIS = (short) 0x29;
+
+ /** Constant for the "*" key */
+ public static final short VK_ASTERISK = (short) 0x2A;
+
+ /** Constant for the "+" key. */
+ public static final short VK_PLUS = (short) 0x2B;
+
+ /** Constant for the comma key, "," */
+ public static final short VK_COMMA = (short) 0x2C;
+
+ /** Constant for the minus key, "-" */
+ public static final short VK_MINUS = (short) 0x2D;
+
+ /** Constant for the period key, "." */
+ public static final short VK_PERIOD = (short) 0x2E;
+
+ /** Constant for the forward slash key, "/" */
+ public static final short VK_SLASH = (short) 0x2F;
+
+ /** VK_0 thru VK_9 are the same as UTF16/ASCII '0' thru '9' [0x30 - 0x39] */
+ public static final short VK_0 = (short) 0x30;
+ /** See {@link #VK_0}. */
+ public static final short VK_1 = (short) 0x31;
+ /** See {@link #VK_0}. */
+ public static final short VK_2 = (short) 0x32;
+ /** See {@link #VK_0}. */
+ public static final short VK_3 = (short) 0x33;
+ /** See {@link #VK_0}. */
+ public static final short VK_4 = (short) 0x34;
+ /** See {@link #VK_0}. */
+ public static final short VK_5 = (short) 0x35;
+ /** See {@link #VK_0}. */
+ public static final short VK_6 = (short) 0x36;
+ /** See {@link #VK_0}. */
+ public static final short VK_7 = (short) 0x37;
+ /** See {@link #VK_0}. */
+ public static final short VK_8 = (short) 0x38;
+ /** See {@link #VK_0}. */
+ public static final short VK_9 = (short) 0x39;
+
+ /** Constant for the ":" key. */
+ public static final short VK_COLON = (short) 0x3A;
+
+ /** Constant for the semicolon key, ";" */
+ public static final short VK_SEMICOLON = (short) 0x3B;
+
+ /** Constant for the equals key, "<" */
+ public static final short VK_LESS = (short) 0x3C;
+
+ /** Constant for the equals key, "=" */
+ public static final short VK_EQUALS = (short) 0x3D;
+
+ /** Constant for the equals key, ">" */
+ public static final short VK_GREATER = (short) 0x3E;
+
+ /** Constant for the equals key, "?" */
+ public static final short VK_QUESTIONMARK = (short) 0x3F;
+
+ /** Constant for the equals key, "@" */
+ public static final short VK_AT = (short) 0x40;
+
+ /** VK_A thru VK_Z are the same as Capital UTF16/ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+ public static final short VK_A = (short) 0x41;
+ /** See {@link #VK_A}. */
+ public static final short VK_B = (short) 0x42;
+ /** See {@link #VK_A}. */
+ public static final short VK_C = (short) 0x43;
+ /** See {@link #VK_A}. */
+ public static final short VK_D = (short) 0x44;
+ /** See {@link #VK_A}. */
+ public static final short VK_E = (short) 0x45;
+ /** See {@link #VK_A}. */
+ public static final short VK_F = (short) 0x46;
+ /** See {@link #VK_A}. */
+ public static final short VK_G = (short) 0x47;
+ /** See {@link #VK_A}. */
+ public static final short VK_H = (short) 0x48;
+ /** See {@link #VK_A}. */
+ public static final short VK_I = (short) 0x49;
+ /** See {@link #VK_A}. */
+ public static final short VK_J = (short) 0x4A;
+ /** See {@link #VK_A}. */
+ public static final short VK_K = (short) 0x4B;
+ /** See {@link #VK_A}. */
+ public static final short VK_L = (short) 0x4C;
+ /** See {@link #VK_A}. */
+ public static final short VK_M = (short) 0x4D;
+ /** See {@link #VK_A}. */
+ public static final short VK_N = (short) 0x4E;
+ /** See {@link #VK_A}. */
+ public static final short VK_O = (short) 0x4F;
+ /** See {@link #VK_A}. */
+ public static final short VK_P = (short) 0x50;
+ /** See {@link #VK_A}. */
+ public static final short VK_Q = (short) 0x51;
+ /** See {@link #VK_A}. */
+ public static final short VK_R = (short) 0x52;
+ /** See {@link #VK_A}. */
+ public static final short VK_S = (short) 0x53;
+ /** See {@link #VK_A}. */
+ public static final short VK_T = (short) 0x54;
+ /** See {@link #VK_A}. */
+ public static final short VK_U = (short) 0x55;
+ /** See {@link #VK_A}. */
+ public static final short VK_V = (short) 0x56;
+ /** See {@link #VK_A}. */
+ public static final short VK_W = (short) 0x57;
+ /** See {@link #VK_A}. */
+ public static final short VK_X = (short) 0x58;
+ /** See {@link #VK_A}. */
+ public static final short VK_Y = (short) 0x59;
+ /** See {@link #VK_A}. */
+ public static final short VK_Z = (short) 0x5A;
+
+ /** Constant for the open bracket key, "[" */
+ public static final short VK_OPEN_BRACKET = (short) 0x5B;
+
+ /**Constant for the back slash key, "\" */
+ public static final short VK_BACK_SLASH = (short) 0x5C;
+
+ /** Constant for the close bracket key, "]" */
+ public static final short VK_CLOSE_BRACKET = (short) 0x5D;
+
+ /** Constant for the "^" key. */
+ public static final short VK_CIRCUMFLEX = (short) 0x5E;
+
+ /** Constant for the "_" key */
+ public static final short VK_UNDERSCORE = (short) 0x5F;
+
+ /** Constant for the "`" key */
+ public static final short VK_BACK_QUOTE = (short) 0x60;
+
+ /** Small UTF/ASCII 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym. */
+
+ /**
+ * Constant for the F<i>n</i> function keys.
+ * <p>
+ * F1..F24, i.e. F<i>n</i>, are mapped from on <code>0x60+n</code> -> <code>[0x61 .. 0x78]</code>.
+ * </p>
+ * <p>
+ * <b>Warning:</b> The F<i>n</i> function keys <b>do collide</b> with unicode characters small 'a' thru 'x'!<br/>
+ * See <a href="#unicodeCollision">Unicode Collision</a> for details.
+ * </p>
+ */
+ public static final short VK_F1 = (short) ( 0x60+ 1 );
+
+ /** Constant for the F2 function key. See {@link #VK_F1}. */
+ public static final short VK_F2 = (short) ( 0x60+ 2 );
+
+ /** Constant for the F3 function key. See {@link #VK_F1}. */
+ public static final short VK_F3 = (short) ( 0x60+ 3 );
+
+ /** Constant for the F4 function key. See {@link #VK_F1}. */
+ public static final short VK_F4 = (short) ( 0x60+ 4 );
+
+ /** Constant for the F5 function key. See {@link #VK_F1}. */
+ public static final short VK_F5 = (short) ( 0x60+ 5 );
+
+ /** Constant for the F6 function key. See {@link #VK_F1}. */
+ public static final short VK_F6 = (short) ( 0x60+ 6 );
+
+ /** Constant for the F7 function key. See {@link #VK_F1}. */
+ public static final short VK_F7 = (short) ( 0x60+ 7 );
+
+ /** Constant for the F8 function key. See {@link #VK_F1}. */
+ public static final short VK_F8 = (short) ( 0x60+ 8 );
+
+ /** Constant for the F9 function key. See {@link #VK_F1}. */
+ public static final short VK_F9 = (short) ( 0x60+ 9 );
+
+ /** Constant for the F11 function key. See {@link #VK_F1}. */
+ public static final short VK_F10 = (short) ( 0x60+10 );
+
+ /** Constant for the F11 function key. See {@link #VK_F1}. */
+ public static final short VK_F11 = (short) ( 0x60+11 );
+
+ /** Constant for the F12 function key. See {@link #VK_F1}.*/
+ public static final short VK_F12 = (short) ( 0x60+12 );
+
+ /** Constant for the F13 function key. See {@link #VK_F1}. */
+ public static final short VK_F13 = (short) ( 0x60+13 );
+
+ /** Constant for the F14 function key. See {@link #VK_F1}. */
+ public static final short VK_F14 = (short) ( 0x60+14 );
+
+ /** Constant for the F15 function key. See {@link #VK_F1}. */
+ public static final short VK_F15 = (short) ( 0x60+15 );
+
+ /** Constant for the F16 function key. See {@link #VK_F1}. */
+ public static final short VK_F16 = (short) ( 0x60+16 );
+
+ /** Constant for the F17 function key. See {@link #VK_F1}. */
+ public static final short VK_F17 = (short) ( 0x60+17 );
+
+ /** Constant for the F18 function key. See {@link #VK_F1}. */
+ public static final short VK_F18 = (short) ( 0x60+18 );
+
+ /** Constant for the F19 function key. See {@link #VK_F1}. */
+ public static final short VK_F19 = (short) ( 0x60+19 );
+
+ /** Constant for the F20 function key. See {@link #VK_F1}. */
+ public static final short VK_F20 = (short) ( 0x60+20 );
+
+ /** Constant for the F21 function key. See {@link #VK_F1}. */
+ public static final short VK_F21 = (short) ( 0x60+21 );
+
+ /** Constant for the F22 function key. See {@link #VK_F1}. */
+ public static final short VK_F22 = (short) ( 0x60+22 );
+
+ /** Constant for the F23 function key. See {@link #VK_F1}. */
+ public static final short VK_F23 = (short) ( 0x60+23 );
+
+ /** Constant for the F24 function key. See {@link #VK_F1}. */
+ public static final short VK_F24 = (short) ( 0x60+24 );
+
+
+ /** Constant for the "{" key */
+ public static final short VK_LEFT_BRACE = (short) 0x7B;
+ /** Constant for the "|" key */
+ public static final short VK_PIPE = (short) 0x7C;
+ /** Constant for the "}" key */
+ public static final short VK_RIGHT_BRACE = (short) 0x7D;
+
+ /** Constant for the "~" key, matching ASCII */
+ public static final short VK_TILDE = (short) 0x7E;
+
+ //
+ // Unicode: Non printable controls: [0x7F - 0x9F]
+ //
+ // Numpad keys [0x7F - 0x8E] are printable
+ //
+
+ /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+ public static final short VK_SEPARATOR = (short) 0x7F;
+
+ /** Numeric keypad VK_NUMPAD0 thru VK_NUMPAD9 are mapped to UTF control (0x80 - 0x89). Non printable UTF control. */
+ public static final short VK_NUMPAD0 = (short) 0x80;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD1 = (short) 0x81;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD2 = (short) 0x82;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD3 = (short) 0x83;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD4 = (short) 0x84;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD5 = (short) 0x85;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD6 = (short) 0x86;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD7 = (short) 0x87;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD8 = (short) 0x88;
+ /** See {@link #VK_NUMPAD0}. */
+ public static final short VK_NUMPAD9 = (short) 0x89;
+
+ /** Numeric keypad <b>decimal separator</b> key. Non printable UTF control. */
+ public static final short VK_DECIMAL = (short) 0x8A;
+
+ /** Numeric keypad <b>add</b> key. Non printable UTF control. */
+ public static final short VK_ADD = (short) 0x8B;
+
+ /** Numeric keypad <b>subtract</b> key. Non printable UTF control. */
+ public static final short VK_SUBTRACT = (short) 0x8C;
+
+ /** Numeric keypad <b>multiply</b> key. Non printable UTF control. */
+ public static final short VK_MULTIPLY = (short) 0x8D;
+
+ /** Numeric keypad <b>divide</b> key. Non printable UTF control. */
+ public static final short VK_DIVIDE = (short) 0x8E;
+
+ /** Constant for the DEL key, matching ASCII. Non printable UTF control. */
+ public static final short VK_DELETE = (short) 0x93;
+
+ /** Numeric keypad <b>num lock</b> key. Non printable UTF control. */
+ public static final short VK_NUM_LOCK = (short) 0x94;
+
+ /** Constant for the cursor- or numerical-pad <b>left</b> arrow key. Non printable UTF control. */
+ public static final short VK_LEFT = (short) 0x95;
+
+ /** Constant for the cursor- or numerical-pad <b>up</b> arrow key. Non printable UTF control. */
+ public static final short VK_UP = (short) 0x96;
+
+ /** Constant for the cursor- or numerical-pad <b>right</b> arrow key. Non printable UTF control. */
+ public static final short VK_RIGHT = (short) 0x97;
+
+ /** Constant for the cursor- or numerical pad <b>down</b> arrow key. Non printable UTF control. */
+ public static final short VK_DOWN = (short) 0x98;
+
+ /** Constant for the Context Menu key. Non printable UTF control. */
+ public static final short VK_CONTEXT_MENU = (short) 0x99;
/**
- * Constant for the "@" key.
- * @since 1.2
- */
- public static final int VK_AT = 0x0200;
-
- /**
- * Constant for the ":" key.
- * @since 1.2
- */
- public static final int VK_COLON = 0x0201;
-
- /**
- * Constant for the "^" key.
- * @since 1.2
- */
- public static final int VK_CIRCUMFLEX = 0x0202;
-
- /**
- * Constant for the "$" key.
- * @since 1.2
- */
- public static final int VK_DOLLAR = 0x0203;
-
- /**
- * Constant for the Euro currency sign key.
- * @since 1.2
- */
- public static final int VK_EURO_SIGN = 0x0204;
-
- /**
- * Constant for the "!" key.
- * @since 1.2
- */
- public static final int VK_EXCLAMATION_MARK = 0x0205;
-
- /**
- * Constant for the inverted exclamation mark key.
- * @since 1.2
- */
- public static final int VK_INVERTED_EXCLAMATION_MARK = 0x0206;
-
- /**
- * Constant for the "(" key.
- * @since 1.2
- */
- public static final int VK_LEFT_PARENTHESIS = 0x0207;
-
- /**
- * Constant for the "#" key.
- * @since 1.2
+ * Constant for the MS "Windows" function key.
+ * It is used for both the left and right version of the key.
*/
- public static final int VK_NUMBER_SIGN = 0x0208;
-
+ public static final short VK_WINDOWS = (short) 0x9A;
+
+ /** Constant for the Meta function key. */
+ public static final short VK_META = (short) 0x9B;
+
+ /** Constant for the Help function key. */
+ public static final short VK_HELP = (short) 0x9C;
+
+ /** Constant for the Compose function key. */
+ public static final short VK_COMPOSE = (short) 0x9D;
+
+ /** Constant for the Begin function key. */
+ public static final short VK_BEGIN = (short) 0x9E;
+
+ /** Constant for the Stop function key. */
+ public static final short VK_STOP = (short) 0x9F;
+
+ //
+ // Unicode: Printable [0x00A0 - 0xDFFF]
+ //
+
+ /** Constant for the inverted exclamation mark key. */
+ public static final short VK_INVERTED_EXCLAMATION_MARK = (short) 0xA1;
+
+ /** Constant for the Euro currency sign key. */
+ public static final short VK_EURO_SIGN = (short) 0x20AC;
+
+ //
+ // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+ //
+
+ /* for Sun keyboards */
+ public static final short VK_CUT = (short) 0xF879;
+ public static final short VK_COPY = (short) 0xF87A;
+ public static final short VK_PASTE = (short) 0xF87B;
+ public static final short VK_UNDO = (short) 0xF87C;
+ public static final short VK_AGAIN = (short) 0xF87D;
+ public static final short VK_FIND = (short) 0xF87E;
+ public static final short VK_PROPS = (short) 0xF87F;
+
+ /* for input method support on Asian Keyboards */
+
/**
- * Constant for the "+" key.
- * @since 1.2
+ * Constant for the input method on/off key.
*/
- public static final int VK_PLUS = 0x0209;
-
+ /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
+ public static final short VK_INPUT_METHOD_ON_OFF = (short) 0xF890;
+
/**
- * Constant for the ")" key.
- * @since 1.2
+ * Constant for the Code Input function key.
*/
- public static final int VK_RIGHT_PARENTHESIS = 0x020A;
-
+ /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
+ public static final short VK_CODE_INPUT = (short) 0xF891;
+
/**
- * Constant for the "_" key.
- * @since 1.2
+ * Constant for the Roman Characters function key.
*/
- public static final int VK_UNDERSCORE = 0x020B;
-
+ /* Japanese PC 106 keyboard: roumaji */
+ public static final short VK_ROMAN_CHARACTERS = (short) 0xF892;
+
/**
- * Constant for the Microsoft Windows "Windows" key.
- * It is used for both the left and right version of the key.
- * @see #getKeyLocation()
- * @since 1.5
+ * Constant for the All Candidates function key.
*/
- public static final int VK_WINDOWS = 0x020C;
-
+ /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
+ public static final short VK_ALL_CANDIDATES = (short) 0xF893;
+
/**
- * Constant for the Microsoft Windows Context Menu key.
- * @since 1.5
+ * Constant for the Previous Candidate function key.
*/
- public static final int VK_CONTEXT_MENU = 0x020D;
-
- /* for input method support on Asian Keyboards */
-
- /* not clear what this means - listed in Microsoft Windows API */
- public static final int VK_FINAL = 0x0018;
-
- /** Constant for the Convert function key. */
- /* Japanese PC 106 keyboard, Japanese Solaris keyboard: henkan */
- public static final int VK_CONVERT = 0x001C;
-
- /** Constant for the Don't Convert function key. */
- /* Japanese PC 106 keyboard: muhenkan */
- public static final int VK_NONCONVERT = 0x001D;
-
- /** Constant for the Accept or Commit function key. */
- /* Japanese Solaris keyboard: kakutei */
- public static final int VK_ACCEPT = 0x001E;
-
- /* not clear what this means - listed in Microsoft Windows API */
- public static final int VK_MODECHANGE = 0x001F;
-
- /* replaced by VK_KANA_LOCK for Microsoft Windows and Solaris;
- might still be used on other platforms */
- public static final int VK_KANA = 0x0015;
-
- /* replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris;
- might still be used for other platforms */
- public static final int VK_KANJI = 0x0019;
+ /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
+ public static final short VK_PREVIOUS_CANDIDATE = (short) 0xF894;
/**
* Constant for the Alphanumeric function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: eisuu */
- public static final int VK_ALPHANUMERIC = 0x00F0;
-
+ public static final short VK_ALPHANUMERIC = (short) 0xF895;
+
/**
* Constant for the Katakana function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: katakana */
- public static final int VK_KATAKANA = 0x00F1;
-
+ public static final short VK_KATAKANA = (short) 0xF896;
+
/**
* Constant for the Hiragana function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: hiragana */
- public static final int VK_HIRAGANA = 0x00F2;
-
+ public static final short VK_HIRAGANA = (short) 0xF897;
+
/**
* Constant for the Full-Width Characters function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: zenkaku */
- public static final int VK_FULL_WIDTH = 0x00F3;
-
+ public static final short VK_FULL_WIDTH = (short) 0xF898;
+
/**
* Constant for the Half-Width Characters function key.
- * @since 1.2
*/
/* Japanese PC 106 keyboard: hankaku */
- public static final int VK_HALF_WIDTH = 0x00F4;
-
- /**
- * Constant for the Roman Characters function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard: roumaji */
- public static final int VK_ROMAN_CHARACTERS = 0x00F5;
-
- /**
- * Constant for the All Candidates function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */
- public static final int VK_ALL_CANDIDATES = 0x0100;
-
- /**
- * Constant for the Previous Candidate function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */
- public static final int VK_PREVIOUS_CANDIDATE = 0x0101;
-
- /**
- * Constant for the Code Input function key.
- * @since 1.2
- */
- /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */
- public static final int VK_CODE_INPUT = 0x0102;
-
+ public static final short VK_HALF_WIDTH = (short) 0xF89A;
+
/**
* Constant for the Japanese-Katakana function key.
* This key switches to a Japanese input method and selects its Katakana input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard - VK_JAPANESE_HIRAGANA + SHIFT */
- public static final int VK_JAPANESE_KATAKANA = 0x0103;
-
+ public static final short VK_JAPANESE_KATAKANA = (short) 0xF89B;
+
/**
* Constant for the Japanese-Hiragana function key.
* This key switches to a Japanese input method and selects its Hiragana input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard */
- public static final int VK_JAPANESE_HIRAGANA = 0x0104;
-
+ public static final short VK_JAPANESE_HIRAGANA = (short) 0xF89C;
+
/**
* Constant for the Japanese-Roman function key.
* This key switches to a Japanese input method and selects its Roman-Direct input mode.
- * @since 1.2
*/
/* Japanese Macintosh keyboard */
- public static final int VK_JAPANESE_ROMAN = 0x0105;
+ public static final short VK_JAPANESE_ROMAN = (short) 0xF89D;
/**
* Constant for the locking Kana function key.
* This key locks the keyboard into a Kana layout.
- * @since 1.3
*/
/* Japanese PC 106 keyboard with special Windows driver - eisuu + Control; Japanese Solaris keyboard: kana */
- public static final int VK_KANA_LOCK = 0x0106;
+ public static final short VK_KANA_LOCK = (short) 0xF89F;
/**
- * Constant for the input method on/off key.
- * @since 1.3
+ * Constant for Keyboard became invisible, e.g. Android's soft keyboard Back button hit while keyboard is visible.
*/
- /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */
- public static final int VK_INPUT_METHOD_ON_OFF = 0x0107;
-
- /* for Sun keyboards */
- /** @since 1.2 */
- public static final int VK_CUT = 0xFFD1;
- /** @since 1.2 */
- public static final int VK_COPY = 0xFFCD;
- /** @since 1.2 */
- public static final int VK_PASTE = 0xFFCF;
- /** @since 1.2 */
- public static final int VK_UNDO = 0xFFCB;
- /** @since 1.2 */
- public static final int VK_AGAIN = 0xFFC9;
- /** @since 1.2 */
- public static final int VK_FIND = 0xFFD0;
- /** @since 1.2 */
- public static final int VK_PROPS = 0xFFCA;
- /** @since 1.2 */
- public static final int VK_STOP = 0xFFC8;
-
- /**
- * Constant for the Compose function key.
- * @since 1.2
- */
- public static final int VK_COMPOSE = 0xFF20;
-
- /**
- * Constant for the AltGraph function key.
- * @since 1.2
- */
- public static final int VK_ALT_GRAPH = 0xFF7E;
-
- /**
- * Constant for the Begin key.
- * @since 1.5
- */
- public static final int VK_BEGIN = 0xFF58;
+ public static final short VK_KEYBOARD_INVISIBLE = (short) 0xF8FF;
- /**
- * This value is used to indicate that the keyCode is unknown.
- * KEY_TYPED events do not have a keyCode value; this value
- * is used instead.
- */
- public static final int VK_UNDEFINED = 0x0;
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyListener.java b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
index dae343d80..4b16ab61e 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,15 +29,33 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+/**
+ * Listener for {@link KeyEvent}s.
+ *
+ * @see KeyEvent
+ */
public interface KeyListener extends NEWTEventListener
{
- public void keyPressed(KeyEvent e);
- public void keyReleased(KeyEvent e);
- public void keyTyped(KeyEvent e) ;
+ /** A key has been {@link KeyEvent#EVENT_KEY_PRESSED pressed}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}. */
+ public void keyPressed(KeyEvent e);
+
+ /**
+ * A key has been {@link KeyEvent#EVENT_KEY_RELEASED released}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}.
+ * <p>
+ * To simulated the removed <code>keyTyped(KeyEvent e)</code> semantics,
+ * simply apply the following constraints upfront and bail out if not matched, i.e.:
+ * <pre>
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ * </pre>
+ * </p>
+ */
+ public void keyReleased(KeyEvent e);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
new file mode 100644
index 000000000..03242e147
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorEvent.java
@@ -0,0 +1,73 @@
+/**
+ * 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 com.jogamp.newt.event;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+@SuppressWarnings("serial")
+public class MonitorEvent extends OutputEvent {
+ public static final short EVENT_MONITOR_MODE_CHANGE_NOTIFY = 600;
+ public static final short EVENT_MONITOR_MODE_CHANGED = 601;
+
+ private final MonitorMode mode;
+
+ public MonitorEvent (short eventType, MonitorDevice source, long when, MonitorMode mode) {
+ super(eventType, source, when);
+ this.mode = mode;
+ }
+
+ /** Returns the {@link #getSource() source}, which is a {@link MonitorDevice}. */
+ public final MonitorDevice getMonitor() { return (MonitorDevice)source; }
+
+ public final MonitorMode getMode() { return mode; }
+
+ public static String getEventTypeString(short type) {
+ switch(type) {
+ case EVENT_MONITOR_MODE_CHANGE_NOTIFY: return "EVENT_MONITOR_MODE_CHANGE_NOTIFY";
+ case EVENT_MONITOR_MODE_CHANGED: return "EVENT_MONITOR_MODE_CHANGED";
+ default: return "unknown (" + type + ")";
+ }
+ }
+
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("MonitorEvent[").append(getEventTypeString(getEventType())).append(", source ").append(source)
+ .append(", mode ").append(mode).append(", ");
+ return super.toString(sb).append("]");
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
index 7bca23cfe..11e23def1 100644
--- a/src/newt/classes/com/jogamp/newt/event/ScreenModeListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MonitorModeListener.java
@@ -28,12 +28,10 @@
package com.jogamp.newt.event;
-import com.jogamp.newt.ScreenMode;
+public interface MonitorModeListener {
+ /** called before the monitor mode will be changed */
+ void monitorModeChangeNotify(MonitorEvent me);
-public interface ScreenModeListener {
- /** called before the screen mode will be changed */
- void screenModeChangeNotify(ScreenMode sm);
-
- /** called after the screen mode has been changed */
- void screenModeChanged(ScreenMode sm, boolean success);
+ /** called after the monitor mode has been changed */
+ void monitorModeChanged(MonitorEvent me, boolean success);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
index 3607ae634..98252fe14 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,30 +20,38 @@
* 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 com.jogamp.newt.event;
public abstract class MouseAdapter implements MouseListener
{
+ @Override
public void mouseClicked(MouseEvent e) {
}
+ @Override
public void mouseEntered(MouseEvent e) {
}
+ @Override
public void mouseExited(MouseEvent e) {
}
+ @Override
public void mousePressed(MouseEvent e) {
}
+ @Override
public void mouseReleased(MouseEvent e) {
}
+ @Override
public void mouseMoved(MouseEvent e) {
}
+ @Override
public void mouseDragged(MouseEvent e) {
}
+ @Override
public void mouseWheelMoved(MouseEvent e) {
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
index ceaf7d47a..272e4beb0 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,186 +29,573 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+/**
+ * Pointer event of type {@link PointerType}.
+ * <p>
+ * The historical misleading class name may change in the future to <code>PointerEvent</code>.
+ * </p>
+ * <p>
+ * http://www.w3.org/Submission/pointer-events/#pointerevent-interface
+ * </p>
+ * <a name="multiPtrEvent"><h5>Multiple-Pointer Events</h5></a>
+ * <p>
+ * In case an instance represents a multiple-pointer event, i.e. {@link #getPointerCount()} is &gt; 1,
+ * the first data element of the multiple-pointer fields represents the pointer triggering this event.<br/>
+ * For example {@link #getX(int) e.getX(0)} at {@link #EVENT_MOUSE_PRESSED} returns the data of the pressed pointer, etc.
+ * </p>
+ * <p>
+ * A {@link #getButton() button value} of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ * <p>
+ * A {@link #getPointerId(int) pointer-ID} of -1 denotes no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ * <p>
+ * {@link #getButton() Button values} are mapped from and to {@link #getPointerId(int) pointer-IDs} as follows:
+ * <code>
+ * getPointerId(0) == getButton() - 1
+ * </code>.
+ * </p>
+ * <p>
+ * If representing a multiple-pointer event, the {@link #getButton() button number} is mapped to the <i>first {@link #getPointerId(int) pointer ID}</i>
+ * triggering the event and the {@link InputEvent#BUTTON1_MASK button mask bits} in the {@link #getModifiers() modifiers}
+ * field represent the pressed pointer IDs.<br>
+ * Hence users can query the pressed button count as well as the pressed pointer count via {@link InputEvent#getButtonDownCount()}
+ * or use the simple query {@link InputEvent#isAnyButtonDown()}.
+ * </p>
+ */
@SuppressWarnings("serial")
public class MouseEvent extends InputEvent
{
+ /** Class of pointer types */
+ public static enum PointerClass implements InputEvent.InputClass {
+ Offscreen, Onscreen, Undefined;
+ }
+
+ /** Type of pointer devices */
+ public static enum PointerType implements InputEvent.InputType {
+ /** {@link PointerClass#Offscreen} mouse. Ordinal 0. */
+ Mouse(PointerClass.Offscreen),
+ /** {@link PointerClass#Offscreen} touch pad, usually using fingers. Ordinal 1. */
+ TouchPad(PointerClass.Offscreen),
+ /** {@link PointerClass#Onscreen} touch screen, usually using fingers. Ordinal 2. */
+ TouchScreen(PointerClass.Onscreen),
+ /** {@link PointerClass#Onscreen} pen usually on screen? Ordinal 3. FIXME*/
+ Pen(PointerClass.Onscreen),
+ /** {@link PointerClass#Undefined} ?. Ordinal 4. */
+ Undefined(PointerClass.Undefined);
+
+ public PointerClass getPointerClass() { return pc; }
+
+ /**
+ * Returns the matching PointerType value corresponding to the given PointerType's integer ordinal.
+ * <pre>
+ * given:
+ * ordinal = enumValue.ordinal()
+ * reverse:
+ * enumValue = EnumClass.values()[ordinal]
+ * </pre>
+ * @throws IllegalArgumentException if the given ordinal is out of range, i.e. not within [ 0 .. PointerType.values().length-1 ]
+ */
+ public static PointerType valueOf(int ordinal) throws IllegalArgumentException {
+ final PointerType[] all = PointerType.values();
+ if( 0 <= ordinal && ordinal < all.length ) {
+ return all[ordinal];
+ }
+ throw new IllegalArgumentException("Ordinal "+ordinal+" out of range of PointerType.values()[0.."+(all.length-1)+"]");
+ }
+
+ /**
+ * Returns the PointerType array of matching PointerType values corresponding to the given PointerType's integer ordinal values.
+ * <p>
+ * See {@link #valueOf(int)}.
+ * </p>
+ * @throws IllegalArgumentException if one of the given ordinal values is out of range, i.e. not within [ 0 .. PointerType.values().length-1 ]
+ */
+ public static PointerType[] valuesOf(int[] ordinals) throws IllegalArgumentException {
+ final int count = ordinals.length;
+ final PointerType[] types = new PointerType[count];
+ for(int i=count-1; i>=0; i--) {
+ types[i] = PointerType.valueOf(ordinals[i]);
+ }
+ return types;
+ }
+
+ private PointerType(PointerClass pc) {
+ this.pc = pc;
+ }
+ PointerClass pc;
+ }
+
/** ID for button 1, value <code>1</code> */
- public static final int BUTTON1 = 1;
+ public static final short BUTTON1 = 1;
/** ID for button 2, value <code>2</code> */
- public static final int BUTTON2 = 2;
+ public static final short BUTTON2 = 2;
/** ID for button 3, value <code>3</code> */
- public static final int BUTTON3 = 3;
+ public static final short BUTTON3 = 3;
/** ID for button 4, value <code>4</code> */
- public static final int BUTTON4 = 4;
+ public static final short BUTTON4 = 4;
/** ID for button 5, value <code>5</code> */
- public static final int BUTTON5 = 5;
+ public static final short BUTTON5 = 5;
/** ID for button 6, value <code>6</code> */
- public static final int BUTTON6 = 6;
- /** Number of buttons, value <code>6</code> */
- public static final int BUTTON_NUMBER = 6;
+ public static final short BUTTON6 = 6;
+ /** ID for button 6, value <code>7</code> */
+ public static final short BUTTON7 = 7;
+ /** ID for button 6, value <code>8</code> */
+ public static final short BUTTON8 = 8;
+ /** ID for button 6, value <code>9</code> */
+ public static final short BUTTON9 = 9;
+
+ /** Maximum number of buttons, value <code>16</code> */
+ public static final short BUTTON_COUNT = 16;
+
+ /**
+ * Maximum number of buttons, value <code>16</code>.
+ * @deprecated Use {@link #BUTTON_COUNT} .. semantics.
+ */
+ public static final short BUTTON_NUMBER = 16;
- public static final int getClickTimeout() {
- return 300;
+ /** Returns the 3-axis XYZ rotation array by given rotation on Y axis or X axis (if SHIFT_MASK is given in mods). */
+ public static final float[] getRotationXYZ(final float rotationXorY, final int mods) {
+ final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+ if( 0 != ( mods & InputEvent.SHIFT_MASK ) ) {
+ rotationXYZ[0] = rotationXorY;
+ } else {
+ rotationXYZ[1] = rotationXorY;
+ }
+ return rotationXYZ;
+ }
+
+ public static final short getClickTimeout() {
+ return 300;
}
- public MouseEvent(int eventType, Object source, long when,
- int modifiers, int x, int y, int clickCount, int button,
- int rotation)
+ /**
+ * Constructor for traditional one-pointer event.
+ *
+ * @param eventType
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param x X-axis
+ * @param y Y-axis
+ * @param clickCount Mouse-button click-count
+ * @param button button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * @param rotationXYZ Rotation of all axis
+ * @param rotationScale Rotation scale
+ */
+ public MouseEvent(short eventType, Object source, long when,
+ int modifiers, int x, int y, short clickCount, short button,
+ float[] rotationXYZ, float rotationScale)
{
- super(eventType, source, when, modifiers);
+ super(eventType, source, when, modifiers);
this.x = new int[]{x};
this.y = new int[]{y};
- this.pressure = new float[]{0};
- this.pointerids = new int[]{-1};
+ switch(eventType) {
+ case EVENT_MOUSE_CLICKED:
+ case EVENT_MOUSE_PRESSED:
+ case EVENT_MOUSE_DRAGGED:
+ this.pressure = constMousePressure1;
+ break;
+ default:
+ this.pressure = constMousePressure0;
+ }
+ this.maxPressure= 1.0f;
+ this.pointerID = new short[] { (short)(button - 1) };
this.clickCount=clickCount;
this.button=button;
- this.wheelRotation = rotation;
+ this.rotationXYZ = rotationXYZ;
+ this.rotationScale = rotationScale;
+ this.pointerType = constMousePointerTypes;
}
- public MouseEvent(int eventType, Object source, long when,
- int modifiers, int[] x, int[] y, float[] pressure, int[] pointerids, int clickCount, int button,
- int rotation)
+ /**
+ * Constructor for a multiple-pointer event.
+ * <p>
+ * First element of multiple-pointer arrays represents the pointer which triggered the event!
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
+ *
+ * @param eventType
+ * @param source
+ * @param when
+ * @param modifiers
+ * @param pointerType PointerType for each pointer (multiple pointer)
+ * @param pointerID Pointer ID for each pointer (multiple pointer). IDs start w/ 0 and are consecutive numbers.
+ * A pointer-ID of -1 may also denote no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * @param x X-axis for each pointer (multiple pointer)
+ * @param y Y-axis for each pointer (multiple pointer)
+ * @param pressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ * @param button Corresponding mouse-button
+ * @param clickCount Mouse-button click-count
+ * @param rotationXYZ Rotation of all axis
+ * @param rotationScale Rotation scale
+ */
+ public MouseEvent(short eventType, Object source, long when, int modifiers,
+ PointerType pointerType[], short[] pointerID,
+ int[] x, int[] y, float[] pressure, float maxPressure,
+ short button, short clickCount, float[] rotationXYZ, float rotationScale)
{
- super(eventType, source, when, modifiers);
+ super(eventType, source, when, modifiers);
this.x = x;
this.y = y;
- if(pointerids.length != pressure.length ||
- pointerids.length != x.length ||
- pointerids.length != y.length) {
+ final int pointerCount = pointerType.length;
+ if(pointerCount != pointerID.length ||
+ pointerCount != x.length ||
+ pointerCount != y.length ||
+ pointerCount != pressure.length) {
throw new IllegalArgumentException("All multiple pointer arrays must be of same size");
}
+ if( 0.0f >= maxPressure ) {
+ throw new IllegalArgumentException("maxPressure must be > 0.0f");
+ }
this.pressure = pressure;
- this.pointerids = pointerids;
+ this.maxPressure= maxPressure;
+ this.pointerID = pointerID;
this.clickCount=clickCount;
this.button=button;
- this.wheelRotation = rotation;
+ this.rotationXYZ = rotationXYZ;
+ this.rotationScale = rotationScale;
+ this.pointerType = pointerType;
}
-
+
+ public MouseEvent createVariant(short newEventType) {
+ return new MouseEvent(newEventType, source, getWhen(), getModifiers(), pointerType, pointerID,
+ x, y, pressure, maxPressure, button, clickCount, rotationXYZ, rotationScale);
+ }
+
/**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
* @return the count of pointers involved in this event
*/
- public int getPointerCount() {
- return x.length;
+ public final int getPointerCount() {
+ return pointerType.length;
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return the {@link PointerType} for the data at index or null if index not available.
+ */
+ public final PointerType getPointerType(int index) {
+ if(0 > index || index >= pointerType.length) {
+ return null;
+ }
+ return pointerType[index];
}
-
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all {@link PointerType}s for all pointers
+ */
+ public final PointerType[] getAllPointerTypes() {
+ return pointerType;
+ }
+
/**
- * @return the pointer id for the data at index.
- * return -1 if index not available.
+ * Return the pointer id for the given index or -1 if index not available.
+ * <p>
+ * IDs start w/ 0 and are consecutive numbers.
+ * </p>
+ * <p>
+ * A pointer-ID of -1 may also denote no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
*/
- public int getPointerId(int index) {
- if(index >= pointerids.length)
+ public final short getPointerId(int index) {
+ if(0 > index || index >= pointerID.length) {
return -1;
- return pointerids[index];
+ }
+ return pointerID[index];
}
-
- public int getButton() {
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return the pointer index for the given pointer id or -1 if id not available.
+ */
+ public final int getPointerIdx(short id) {
+ if( id >= 0 ) {
+ for(int i=pointerID.length-1; i>=0; i--) {
+ if( pointerID[i] == id ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all pointer IDs for all pointers. IDs start w/ 0 and are consecutive numbers.
+ */
+ public final short[] getAllPointerIDs() {
+ return pointerID;
+ }
+
+ /**
+ * Returns the button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * <p>
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ * <p>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * </p>
+ */
+ public final short getButton() {
return button;
}
-
- public int getClickCount() {
+
+ public final short getClickCount() {
return clickCount;
}
- public int getX() {
+
+ public final int getX() {
return x[0];
}
-
- public int getY() {
+
+ public final int getY() {
return y[0];
}
- /**
- * @return x-coord at index where index refers to the
- * data coming from a pointer.
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @return X-Coord associated with the pointer-index.
* @see getPointerId(index)
*/
- public int getX(int index) {
+ public final int getX(int index) {
return x[index];
}
- public int getY(int index) {
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @return Y-Coord associated with the pointer-index.
+ * @see getPointerId(index)
+ */
+ public final int getY(int index) {
return y[index];
}
-
- public float getPressure(){
- return pressure[0];
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all X-Coords for all pointers
+ */
+ public final int[] getAllX() {
+ return x;
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all Y-Coords for all pointers
+ */
+ public final int[] getAllY() {
+ return y;
}
-
+
/**
- * @return the pressure associated with the pointer at index.
- * the value of zero is return if not available.
+ * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code>
+ * @return The pressure associated with the pointer-index 0.
+ * The value of zero is return if not available.
+ * @see #getMaxPressure()
*/
- public float getPressure(int index){
- return pressure[index];
+ public final float getPressure(boolean normalized){
+ return normalized ? pressure[0] / maxPressure : pressure[0];
}
-
+
/**
- * <i>Usually</i> a wheel rotation of <b>&gt; 0 is up</b>,
- * and <b>&lt; 0 is down</b>.<br>
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @param index pointer-index within [0 .. {@link #getPointerCount()}-1]
+ * @param normalized if true, method returns the normalized pressure, i.e. <code>pressure / maxPressure</code>
+ * @return The pressure associated with the pointer-index.
+ * The value of zero is return if not available.
+ * @see #getMaxPressure()
+ */
+ public final float getPressure(int index, boolean normalized){
+ return normalized ? pressure[index] / maxPressure : pressure[index];
+ }
+
+ /**
+ * See details for <a href="#multiPtrEvent">multiple-pointer events</a>.
+ * @return array of all raw, un-normalized pressures for all pointers
+ */
+ public final float[] getAllPressures() {
+ return pressure;
+ }
+
+ /**
+ * Returns the maximum pressure known for the input device generating this event.
+ * <p>
+ * This value may be self calibrating on devices/OS, where no known maximum pressure is known.
+ * Hence subsequent events may return a higher value.
+ * </p>
+ * <p>
+ * Self calibrating maximum pressure is performed on:
+ * <ul>
+ * <li>Android</li>
+ * </ul>
+ * </p>
+ */
+ public final float getMaxPressure() {
+ return maxPressure;
+ }
+
+ /**
+ * Returns a 3-component float array filled with the values of the rotational axis
+ * in the following order: horizontal-, vertical- and z-axis.
+ * <p>
+ * A vertical rotation of <b>&gt; 0.0f is up</b> and <b>&lt; 0.0f is down</b>.
+ * </p>
+ * <p>
+ * A horizontal rotation of <b>&gt; 0.0f is left</b> and <b>&lt; 0.0f is right</b>.
+ * </p>
+ * <p>
+ * A z-axis rotation of <b>&gt; 0.0f is back</b> and <b>&lt; 0.0f is front</b>.
+ * </p>
+ * <p>
* <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior.
* The latter is true for OS X 10.7 (Lion) for example.
+ * </p>
* <p>
- * The events will be send usually in steps of one, ie. <i>-1</i> and <i>1</i>.
+ * On PointerClass {@link PointerClass#Onscreen onscreen} devices, i.e. {@link PointerType#TouchScreen touch screens},
+ * rotation events are usually produced by a 2-finger movement, where horizontal and vertical rotation values are filled.
+ * </p>
+ * <p>
+ * On PointerClass {@link PointerClass#Offscreen offscreen} devices, i.e. {@link PointerType#Mouse mouse},
+ * either the horizontal or the vertical rotation value is filled.
+ * </p>
+ * <p>
+ * The {@link InputEvent#SHIFT_MASK} modifier is set in case <b>|horizontal| &gt; |vertical|</b> value.<br/>
+ * This can be utilized to implement only one 2d rotation direction, you may use {@link #isShiftDown()} to query it.
+ * </p>
+ * <p>
+ * In case the pointer type is {@link PointerType#Mouse mouse},
+ * events are usually send in steps of one, ie. <i>-1.0f</i> and <i>1.0f</i>.
* Higher values may result due to fast scrolling.
+ * Fractional values may result due to slow scrolling with high resolution devices.<br/>
+ * Here the button number refers to the wheel number.
+ * </p>
+ * <p>
+ * In case the pointer type is of class {@link PointerClass#Onscreen}, e.g. {@link PointerType#TouchScreen touch screen},
+ * see {@link #getRotationScale()} for semantics.
+ * </p>
+ */
+ public final float[] getRotation() {
+ return rotationXYZ;
+ }
+
+ /**
+ * Returns the scale used to determine the {@link #getRotation() rotation value},
+ * which semantics depends on the {@link #getPointerType() pointer type's} {@link PointerClass}.
+ * <p>
+ * For {@link PointerClass#Offscreen}, the scale is usually <code>1.0f</code> and denominates
+ * an abstract value without association to a physical value.
* </p>
* <p>
- * The button number refers to the wheel number.
- * </p>
- * @return
+ * For {@link PointerClass#Onscreen}, the scale varies and denominates
+ * the divisor of the distance the finger[s] have moved on the screen.
+ * Hence <code>scale * rotation</code> reproduces the screen distance in pixels the finger[s] have moved.
+ * </p>
*/
- public int getWheelRotation() {
- return wheelRotation;
+ public final float getRotationScale() {
+ return rotationScale;
}
- public String toString() {
- StringBuilder sb = new StringBuilder();
+ @Override
+ public final String toString() {
+ return toString(null).toString();
+ }
+
+ @Override
+ public final StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
sb.append("MouseEvent[").append(getEventTypeString(getEventType()))
.append(", ").append(x).append("/").append(y)
.append(", button ").append(button).append(", count ")
- .append(clickCount).append(", wheel rotation ").append(wheelRotation);
- if(pointerids.length>0) {
- sb.append(", pointer<").append(pointerids.length).append(">[");
- for(int i=0; i<pointerids.length; i++) {
+ .append(clickCount).append(", rotation [").append(rotationXYZ[0]).append(", ").append(rotationXYZ[1]).append(", ").append(rotationXYZ[2]).append("] * ").append(rotationScale);
+ if(pointerID.length>0) {
+ sb.append(", pointer<").append(pointerID.length).append(">[");
+ for(int i=0; i<pointerID.length; i++) {
if(i>0) {
sb.append(", ");
}
- sb.append(pointerids[i]).append(": ")
- .append(x[i]).append(" / ").append(y[i]).append(" ")
- .append(pressure[i]).append("p");
+ sb.append(pointerID[i]).append("/").append(pointerType[i]).append(": ")
+ .append(x[i]).append("/").append(y[i]).append(", ")
+ .append("p[").append(pressure[i]).append("/").append(maxPressure).append("=").append(pressure[i]/maxPressure).append("]");
}
sb.append("]");
- }
- sb.append(", ").append(super.toString()).append("]");
- return sb.toString();
+ }
+ sb.append(", ");
+ return super.toString(sb).append("]");
}
- public static String getEventTypeString(int type) {
+ public static String getEventTypeString(short type) {
switch(type) {
- case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED";
- case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED";
- case EVENT_MOUSE_EXITED: return "EVENT_MOUSE_EXITED";
- case EVENT_MOUSE_PRESSED: return "EVENT_MOUSE_PRESSED";
- case EVENT_MOUSE_RELEASED: return "EVENT_MOUSE_RELEASED";
- case EVENT_MOUSE_MOVED: return "EVENT_MOUSE_MOVED";
- case EVENT_MOUSE_DRAGGED: return "EVENT_MOUSE_DRAGGED";
- case EVENT_MOUSE_WHEEL_MOVED: return "EVENT_MOUSE_WHEEL_MOVED";
- default: return "unknown (" + type + ")";
+ case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED";
+ case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED";
+ case EVENT_MOUSE_EXITED: return "EVENT_MOUSE_EXITED";
+ case EVENT_MOUSE_PRESSED: return "EVENT_MOUSE_PRESSED";
+ case EVENT_MOUSE_RELEASED: return "EVENT_MOUSE_RELEASED";
+ case EVENT_MOUSE_MOVED: return "EVENT_MOUSE_MOVED";
+ case EVENT_MOUSE_DRAGGED: return "EVENT_MOUSE_DRAGGED";
+ case EVENT_MOUSE_WHEEL_MOVED: return "EVENT_MOUSE_WHEEL_MOVED";
+ default: return "unknown (" + type + ")";
}
}
- private final int x[], y[], clickCount, button, wheelRotation;
+
+ /** PointerType for each pointer (multiple pointer) */
+ private final PointerType pointerType[];
+ /**
+ * Pointer-ID for each pointer (multiple pointer). IDs start w/ 0 and are consecutive numbers.
+ * <p>
+ * A pointer-ID of -1 may also denote no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ */
+ private final short pointerID[];
+ /** X-axis for each pointer (multiple pointer) */
+ private final int x[];
+ /** Y-axis for each pointer (multiple pointer) */
+ private final int y[];
+ /** Pressure for each pointer (multiple pointer) */
private final float pressure[];
- private final int pointerids[];
-
- public static final int EVENT_MOUSE_CLICKED = 200;
- public static final int EVENT_MOUSE_ENTERED = 201;
- public static final int EVENT_MOUSE_EXITED = 202;
- public static final int EVENT_MOUSE_PRESSED = 203;
- public static final int EVENT_MOUSE_RELEASED = 204;
- public static final int EVENT_MOUSE_MOVED = 205;
- public static final int EVENT_MOUSE_DRAGGED = 206;
- public static final int EVENT_MOUSE_WHEEL_MOVED = 207;
+ // private final short tiltX[], tiltY[]; // TODO: A generic way for pointer axis information, see Android MotionEvent!
+ private final short clickCount;
+ /**
+ * Returns the button number, e.g. [{@link #BUTTON1}..{@link #BUTTON_COUNT}-1].
+ * <p>
+ * A button value of <code>0</code> denotes no button activity, i.e. {@link PointerType#Mouse} move.
+ * </p>
+ */
+ private final short button;
+ /** Rotation around the X, Y and X axis */
+ private final float[] rotationXYZ;
+ /** Rotation scale */
+ private final float rotationScale;
+ private final float maxPressure;
+
+ private static final float[] constMousePressure0 = new float[]{0f};
+ private static final float[] constMousePressure1 = new float[]{1f};
+ private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
+
+ public static final short EVENT_MOUSE_CLICKED = 200;
+ /** Only generated for {@link PointerType#Mouse} */
+ public static final short EVENT_MOUSE_ENTERED = 201;
+ /** Only generated for {@link PointerType#Mouse} */
+ public static final short EVENT_MOUSE_EXITED = 202;
+ public static final short EVENT_MOUSE_PRESSED = 203;
+ public static final short EVENT_MOUSE_RELEASED = 204;
+ public static final short EVENT_MOUSE_MOVED = 205;
+ public static final short EVENT_MOUSE_DRAGGED = 206;
+ public static final short EVENT_MOUSE_WHEEL_MOVED = 207;
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseListener.java b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
index 7668b755c..6e5142044 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,22 +29,37 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import com.jogamp.newt.event.MouseEvent.PointerType;
+
+/**
+ * Listener for {@link MouseEvent}s.
+ *
+ * @see MouseEvent
+ */
public interface MouseListener extends NEWTEventListener
{
public void mouseClicked(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
public void mouseEntered(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
public void mouseExited(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
public void mouseMoved(MouseEvent e);
public void mouseDragged(MouseEvent e);
-
- /** See {@link MouseEvent#getWheelRotation() } */
+
+ /**
+ * Traditional event name originally produced by a {@link PointerType#Mouse mouse} pointer type.
+ * <p>
+ * Triggered for any rotational pointer events, see
+ * {@link MouseEvent#getRotation()} and {@link MouseEvent#getRotationScale()}.
+ * </p>
+ */
public void mouseWheelMoved(MouseEvent e);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
index 3f3817b91..af800e61e 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
@@ -41,88 +41,35 @@ package com.jogamp.newt.event;
*
* Event type registry:<br>
* <ul>
- * <li> WindowEvent <code>100..10x</code></li>
- * <li> MouseEvent <code>200..20x</code></li>
- * <li> KeyEvent <code>300..30x</code></li>
+ * <li> WindowEvent <code>100..10x</code></li>
+ * <li> MouseEvent <code>200..20x</code></li>
+ * <li> KeyEvent <code>300..30x</code></li>
+ * <li> GestureEvent <code>400..5xx</code></li>
+ * <li> MonitorEvent <code>600..60x</code></li>
* </ul><br>
*/
@SuppressWarnings("serial")
public class NEWTEvent extends java.util.EventObject {
- private final boolean isSystemEvent;
- private final int eventType;
+ /**
+ * See {@link #setConsumed(boolean)} for description.
+ */
+ public static final Object consumedTag = new Object();
+
+ private final short eventType;
private final long when;
private Object attachment;
static final boolean DEBUG = false;
- // 0: NEWTEvent.java
- // 1: InputEvent.java
- // 2: KeyEvent.java
- // 3: com.jogamp.newt.Window
- // 3: com.jogamp.newt.event.awt.AWTNewtEventFactory
- // 2: MouseEvent.java
- // 3: com.jogamp.newt.Window
- // 3: com.jogamp.newt.event.awt.AWTNewtEventFactory
- // 1: WindowEvent.java
- // 2: com.jogamp.newt.Window
- // 2: com.jogamp.newt.event.awt.AWTNewtEventFactory
- //
- // FIXME: verify the isSystemEvent evaluation
- //
- static final String WindowClazzName = "com.jogamp.newt.Window" ;
- static final String AWTNewtEventFactoryClazzName = "com.jogamp.newt.event.awt.AWTNewtEventFactory" ;
-
- /**
- static final boolean evaluateIsSystemEvent(NEWTEvent event, Throwable t) {
- StackTraceElement[] stack = t.getStackTrace();
- if(stack.length==0 || null==stack[0]) {
- return false;
- }
- if(DEBUG) {
- for (int i = 0; i < stack.length && i<5; i++) {
- System.err.println(i+": " + stack[i].getClassName()+ "." + stack[i].getMethodName());
- }
- }
-
- String clazzName = null;
-
- if( event instanceof com.jogamp.newt.event.WindowEvent ) {
- if ( stack.length > 2 ) {
- clazzName = stack[2].getClassName();
- }
- } else if( (event instanceof com.jogamp.newt.event.MouseEvent) ||
- (event instanceof com.jogamp.newt.event.KeyEvent) ) {
- if ( stack.length > 3 ) {
- clazzName = stack[3].getClassName();
- }
- }
-
- boolean res = null!=clazzName && (
- clazzName.equals(WindowClazzName) ||
- clazzName.equals(AWTNewtEventFactoryClazzName) ) ;
- if(DEBUG) {
- System.err.println("system: "+res);
- }
- return res;
- } */
-
- protected NEWTEvent(int eventType, Object source, long when) {
+ protected NEWTEvent(short eventType, Object source, long when) {
super(source);
- // this.isSystemEvent = evaluateIsSystemEvent(this, new Throwable());
- this.isSystemEvent = false; // FIXME: Need a more efficient way to determine system events
this.eventType = eventType;
this.when = when;
this.attachment=null;
}
- /** Indicates whether this event was produced by the system or
- generated by user code. */
- public final boolean isSystemEvent() {
- return isSystemEvent;
- }
-
/** Returns the event type of this event. */
- public final int getEventType() {
+ public final short getEventType() {
return eventType;
}
@@ -131,35 +78,72 @@ public class NEWTEvent extends java.util.EventObject {
return when;
}
- /**
+ /**
* Attach the passed object to this event.<br>
* If an object was previously attached, it will be replaced.<br>
* Attachments to NEWT events allow users to pass on information
- * from one custom listener to another, ie custom listener to listener
+ * from one custom listener to another, ie custom listener to listener
* communication.
* @param attachment User application specific object
*/
public final void setAttachment(Object attachment) {
- this.attachment=attachment;
+ this.attachment = attachment;
}
- /**
+ /**
* @return The user application specific attachment, or null
*/
public final Object getAttachment() {
return attachment;
}
- public String toString() {
- return "NEWTEvent[sys:"+isSystemEvent()+", source:"+getSource().getClass().getName()+", when:"+getWhen()+" d "+(System.currentTimeMillis()-getWhen())+"ms]";
+ /**
+ * Returns <code>true</code> if this events has been {@link #setConsumed(boolean) consumed},
+ * otherwise <code>false</code>.
+ * @see #setConsumed(boolean)
+ */
+ public final boolean isConsumed() {
+ return consumedTag == attachment;
}
- public static String toHexString(int hex) {
- return "0x" + Integer.toHexString(hex);
+ /**
+ * If <code>consumed</code> is <code>true</code>, this event is marked as consumed,
+ * ie. the event will not be propagated any further to potential <i>other</i> event listener.
+ * Otherwise the event will be propagated to other event listener, the default.
+ * <p>
+ * The event is marked as being consumed while {@link #setAttachment(Object) attaching}
+ * the {@link #consumedTag}.
+ * </p>
+ * <p>
+ * Events with platform specific actions will be supressed if marked as consumed.
+ * Examples are:
+ * <ul>
+ * <li>{@link KeyEvent#VK_ESCAPE} on Android's BACK button w/ Activity::finish()</li>
+ * <li>{@link KeyEvent#VK_HOME} on Android's HOME button w/ Intend.ACTION_MAIN[Intend.CATEGORY_HOME]</li>
+ * </ul>
+ * </p>
+ */
+ public final void setConsumed(boolean consumed) {
+ if( consumed ) {
+ setAttachment( consumedTag );
+ } else if( consumedTag == attachment ) {
+ setAttachment( null );
+ }
+ }
+
+ @Override
+ public String toString() {
+ return toString(null).toString();
}
- public static String toHexString(long hex) {
- return "0x" + Long.toHexString(hex);
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ return sb.append("NEWTEvent[source:").append(getSource().getClass().getName()).append(", consumed ").append(isConsumed()).append(", when:").append(getWhen()).append(" d ").append((System.currentTimeMillis()-getWhen())).append("ms]");
}
+ public static String toHexString(short hex) {
+ return "0x" + Integer.toHexString( (int)hex & 0x0000FFFF );
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
index 6aa19e5f8..14fba6742 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,18 +20,18 @@
* 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 com.jogamp.newt.event;
public interface NEWTEventConsumer {
- /**
- * Consume the event
+ /**
+ * Consume the event
*
* @return true if the event has been consumed,
* otherwise it returns false for later propagation.
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
index fe224bba6..7dd56ad1e 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventFiFo.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt.event;
import java.util.LinkedList;
diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
index 677136573..f7ee3d739 100644
--- a/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
diff --git a/src/newt/classes/com/jogamp/newt/event/OutputEvent.java b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
new file mode 100644
index 000000000..80c7780f8
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/OutputEvent.java
@@ -0,0 +1,51 @@
+/**
+ * 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 com.jogamp.newt.event;
+
+@SuppressWarnings("serial")
+public abstract class OutputEvent extends NEWTEvent
+{
+ protected OutputEvent(short eventType, Object source, long when) {
+ super(eventType, source, when);
+ }
+
+ /**
+ public String toString() {
+ return toString(null).toString();
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("OutputEvent[");
+ super.toString(sb).append("]");
+ return sb;
+ } */
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java b/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java
new file mode 100644
index 000000000..42f006f08
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/event/PinchToZoomGesture.java
@@ -0,0 +1,228 @@
+/**
+ * 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 com.jogamp.newt.event;
+
+import javax.media.nativewindow.NativeSurface;
+
+import jogamp.newt.Debug;
+
+/**
+ * 2 pointer zoom, a.k.a. <i>pinch to zoom</i>, gesture handler processing {@link MouseEvent}s
+ * while producing {@link ZoomEvent}s if gesture is completed.
+ * <p>
+ * Zoom value lies within [0..2], with 1 as <i>1:1</i>.
+ * </p>
+ * <pre>
+ * - choosing the smallest surface edge (width/height -> x/y)
+ * - tolerating other fingers to be pressed and hence user to add functionality (scale, ..)
+ * </pre>
+ */
+public class PinchToZoomGesture implements GestureHandler {
+ public static final boolean DEBUG = Debug.debug("Window.MouseEvent");
+
+ /** A {@link GestureHandler.GestureEvent} denominating zoom. */
+ @SuppressWarnings("serial")
+ public static class ZoomEvent extends GestureEvent {
+ private final MouseEvent pe;
+ private final float zoom;
+ public ZoomEvent(Object source, long when, int modifiers, GestureHandler handler, MouseEvent pe, float zoom) {
+ super(source, when, modifiers, handler);
+ this.pe = pe;
+ this.zoom = zoom;
+ }
+ /** Triggering {@link MouseEvent} */
+ public final MouseEvent getTrigger() { return pe; }
+ /** Zoom value lies within [0..2], with 1 as <i>1:1</i>. */
+ public final float getZoom() { return zoom; }
+ }
+
+ private final NativeSurface surface;
+ private final boolean allowMorePointer;
+ private float zoom;
+ private int zoomLastEdgeDist;
+ private boolean zoomFirstTouch;
+ private boolean zoomMode;
+ private ZoomEvent zoomEvent;
+ private final short[] pIds = new short[] { -1, -1 };
+
+ /**
+ * @param surface the {@link NativeSurface}, which size is used to compute the relative zoom factor
+ * @param allowMorePointer if false, allow only 2 pressed pointers (safe and recommended), otherwise accept other pointer to be pressed.
+ */
+ public PinchToZoomGesture(NativeSurface surface, boolean allowMorePointer) {
+ clear(true);
+ this.surface = surface;
+ this.allowMorePointer = allowMorePointer;
+ this.zoom = 1f;
+ }
+
+ @Override
+ public String toString() {
+ return "PinchZoom[1stTouch "+zoomFirstTouch+", in "+isWithinGesture()+", has "+(null!=zoomEvent)+", zoom "+zoom+"]";
+ }
+
+ private int gesturePointers(final MouseEvent e, final int excludeIndex) {
+ int j = 0;
+ for(int i=e.getPointerCount()-1; i>=0; i--) {
+ if( excludeIndex != i ) {
+ final int id = e.getPointerId(i);
+ if( pIds[0] == id || pIds[1] == id ) {
+ j++;
+ }
+ }
+ }
+ return j;
+ }
+
+ @Override
+ public void clear(boolean clearStarted) {
+ zoomEvent = null;
+ if( clearStarted ) {
+ zoomLastEdgeDist = 0;
+ zoomFirstTouch = true;
+ zoomMode = false;
+ pIds[0] = -1;
+ pIds[1] = -1;
+ }
+ }
+
+ @Override
+ public boolean isWithinGesture() {
+ return zoomMode;
+ }
+
+ @Override
+ public boolean hasGesture() {
+ return null != zoomEvent;
+ }
+
+ @Override
+ public InputEvent getGestureEvent() {
+ return zoomEvent;
+ }
+
+ /** Zoom value lies within [0..2], with 1 as <i>1:1</i>. */
+ public final float getZoom() {
+ return zoom;
+ }
+ /** Set zoom value within [0..2], with 1 as <i>1:1</i>. */
+ public final void setZoom(float zoom) {
+ this.zoom=zoom;
+ }
+
+ @Override
+ public boolean process(final InputEvent in) {
+ if( null != zoomEvent || !(in instanceof MouseEvent) ) {
+ return true;
+ }
+ final MouseEvent pe = (MouseEvent)in;
+ final int pointerDownCount = pe.getPointerCount();
+
+ if( pe.getPointerType(0).getPointerClass() != MouseEvent.PointerClass.Onscreen ||
+ ( !allowMorePointer && pointerDownCount > 2 ) ) {
+ return false;
+ }
+
+ final int eventType = pe.getEventType();
+ final boolean useY = surface.getWidth() >= surface.getHeight(); // use smallest dimension
+ switch ( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED: {
+ if( 1 == pointerDownCount ) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = -1;
+ } else if ( 2 <= pointerDownCount ) { // && 1 == gesturePointers(pe, 0) /* w/o pressed pointer */) {
+ pIds[0] = pe.getPointerId(0);
+ pIds[1] = pe.getPointerId(1);
+ }
+ if(DEBUG) {
+ System.err.println("XXX1: id0 "+pIds[0]+" -> idx0 "+0+", id1 "+pIds[1]+" -> idx1 "+1);
+ System.err.println(this+".pressed: down "+pointerDownCount+", gPtr "+gesturePointers(pe, -1)+", event "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_RELEASED: {
+ final int gPtr = gesturePointers(pe, 0); // w/o lifted pointer
+ if ( 1 == gPtr ) {
+ zoomFirstTouch = true;
+ zoomMode = false;
+ } else if( 0 == gPtr ) {
+ // all lifted
+ clear(true);
+ }
+ if(DEBUG) {
+ System.err.println(this+".released: down "+pointerDownCount+", gPtr "+gPtr+", event "+pe);
+ }
+ } break;
+
+ case MouseEvent.EVENT_MOUSE_DRAGGED: {
+ if( 2 <= pointerDownCount ) {
+ final int gPtr = gesturePointers(pe, -1);
+ if( 2 == gPtr ) {
+ // same pointers
+ final int p0Idx = pe.getPointerIdx(pIds[0]);
+ final int p1Idx = pe.getPointerIdx(pIds[1]);
+ if( 0 <= p0Idx && 0 <= p1Idx ) {
+ final int edge0 = useY ? pe.getY(p0Idx) : pe.getX(p0Idx);
+ final int edge1 = useY ? pe.getY(p1Idx) : pe.getX(p1Idx);
+ // Diff. 1:1 Zoom: finger-distance to screen-coord
+ if(zoomFirstTouch) {
+ zoomLastEdgeDist = Math.abs(edge0-edge1);
+ zoomFirstTouch=false;
+ zoomMode = true;
+ } else if( zoomMode ) {
+ final int d = Math.abs(edge0-edge1);
+ final int dd = d - zoomLastEdgeDist;
+ final float screenEdge = useY ? surface.getHeight() : surface.getWidth();
+ final float incr = dd / screenEdge; // [-1..1]
+ if(DEBUG) {
+ System.err.println("XXX2: id0 "+pIds[0]+" -> idx0 "+p0Idx+", id1 "+pIds[1]+" -> idx1 "+p1Idx);
+ System.err.println("XXX3: d "+d+", ld "+zoomLastEdgeDist+", dd "+dd+", screen "+screenEdge+" -> incr "+incr+", zoom "+zoom+" -> "+(zoom+incr));
+ }
+ zoom += incr;
+ // clip value
+ if( 2f < zoom ) {
+ zoom = 2f;
+ } else if( 0 > zoom ) {
+ zoom = 0;
+ }
+ zoomLastEdgeDist = d;
+ zoomEvent = new ZoomEvent(pe.getSource(), pe.getWhen(), pe.getModifiers(), this, pe, zoom);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println(this+".dragged: down "+pointerDownCount+", gPtr "+gPtr+", event "+pe);
+ }
+ }
+ } break;
+
+ default:
+ }
+ return null != zoomEvent;
+ }
+}
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
index 98ba5a24d..bbc170958 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt.event;
public class TraceKeyAdapter implements KeyListener {
@@ -40,17 +40,15 @@ public class TraceKeyAdapter implements KeyListener {
this.downstream = downstream;
}
+ @Override
public void keyPressed(KeyEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.keyPressed(e); }
}
+ @Override
public void keyReleased(KeyEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.keyReleased(e); }
}
- public void keyTyped(KeyEvent e) {
- System.err.println(e);
- if(null!=downstream) { downstream.keyTyped(e); }
- }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
index 14ee633a0..db8376034 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceMouseAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt.event;
public class TraceMouseAdapter implements MouseListener {
@@ -40,34 +40,42 @@ public class TraceMouseAdapter implements MouseListener {
this.downstream = downstream;
}
+ @Override
public void mouseClicked(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseClicked(e); }
}
+ @Override
public void mouseEntered(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseEntered(e); }
}
+ @Override
public void mouseExited(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseExited(e); }
}
+ @Override
public void mousePressed(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mousePressed(e); }
}
+ @Override
public void mouseReleased(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseReleased(e); }
}
+ @Override
public void mouseMoved(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseMoved(e); }
}
+ @Override
public void mouseDragged(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseDragged(e); }
}
+ @Override
public void mouseWheelMoved(MouseEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.mouseWheelMoved(e); }
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
index 8542820c4..7b844f059 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt.event;
public class TraceWindowAdapter implements WindowListener {
@@ -40,30 +40,37 @@ public class TraceWindowAdapter implements WindowListener {
this.downstream = downstream;
}
+ @Override
public void windowResized(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowResized(e); }
}
+ @Override
public void windowMoved(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowMoved(e); }
}
+ @Override
public void windowDestroyNotify(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowDestroyNotify(e); }
}
+ @Override
public void windowDestroyed(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowDestroyed(e); }
}
+ @Override
public void windowGainedFocus(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowGainedFocus(e); }
}
+ @Override
public void windowLostFocus(WindowEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowLostFocus(e); }
}
+ @Override
public void windowRepaint(WindowUpdateEvent e) {
System.err.println(e);
if(null!=downstream) { downstream.windowRepaint(e); }
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
index b9e487e9b..ccc627444 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,28 +20,35 @@
* 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 com.jogamp.newt.event;
public abstract class WindowAdapter implements WindowListener
{
+ @Override
public void windowResized(WindowEvent e) {
}
+ @Override
public void windowMoved(WindowEvent e) {
}
+ @Override
public void windowDestroyNotify(WindowEvent e) {
}
+ @Override
public void windowDestroyed(WindowEvent e) {
}
+ @Override
public void windowGainedFocus(WindowEvent e) {
}
+ @Override
public void windowLostFocus(WindowEvent e) {
}
+ @Override
public void windowRepaint(WindowUpdateEvent e) {
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
index f3d62d8c6..2841fd0f6 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowEvent.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
@@ -39,20 +39,21 @@ package com.jogamp.newt.event;
* NEWT will automatically handle component moves and resizes internally, regardless of whether a program is receiving these events or not. <br>
* The actual event semantic, here move and resize, is processed before the event is send.<br>
*/
+@SuppressWarnings("serial")
public class WindowEvent extends NEWTEvent {
- public static final int EVENT_WINDOW_RESIZED = 100;
- public static final int EVENT_WINDOW_MOVED = 101;
- public static final int EVENT_WINDOW_DESTROY_NOTIFY = 102;
- public static final int EVENT_WINDOW_GAINED_FOCUS = 103;
- public static final int EVENT_WINDOW_LOST_FOCUS = 104;
- public static final int EVENT_WINDOW_REPAINT = 105;
- public static final int EVENT_WINDOW_DESTROYED = 106;
+ public static final short EVENT_WINDOW_RESIZED = 100;
+ public static final short EVENT_WINDOW_MOVED = 101;
+ public static final short EVENT_WINDOW_DESTROY_NOTIFY = 102;
+ public static final short EVENT_WINDOW_GAINED_FOCUS = 103;
+ public static final short EVENT_WINDOW_LOST_FOCUS = 104;
+ public static final short EVENT_WINDOW_REPAINT = 105;
+ public static final short EVENT_WINDOW_DESTROYED = 106;
- public WindowEvent(int eventType, Object source, long when) {
+ public WindowEvent(short eventType, Object source, long when) {
super(eventType, source, when);
}
- public static String getEventTypeString(int type) {
+ public static String getEventTypeString(short type) {
switch(type) {
case EVENT_WINDOW_RESIZED: return "WINDOW_RESIZED";
case EVENT_WINDOW_MOVED: return "WINDOW_MOVED";
@@ -64,8 +65,18 @@ public class WindowEvent extends NEWTEvent {
default: return "unknown (" + type + ")";
}
}
+
+ @Override
public String toString() {
- return "WindowEvent["+getEventTypeString(getEventType()) +
- ", " + super.toString() + "]";
+ return toString(null).toString();
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("WindowEvent[").append(getEventTypeString(getEventType())).append(", ");
+ return super.toString(sb).append("]");
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowListener.java b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
index e841a06cf..e097edf23 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowListener.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,11 +29,14 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.event;
+import javax.media.nativewindow.WindowClosingProtocol;
+
+/** NEWT {@link WindowEvent} listener. */
public interface WindowListener extends NEWTEventListener {
/** Window is resized, your application shall respect the new window dimension. A repaint is recommended. */
public void windowResized(WindowEvent e);
@@ -41,10 +44,19 @@ public interface WindowListener extends NEWTEventListener {
/** Window has been moved. */
public void windowMoved(WindowEvent e);
- /** Window will be destroyed. Release of resources is recommended. */
+ /**
+ * Window destruction has been requested.
+ * <p>
+ * Depending on the {@link WindowClosingProtocol#getDefaultCloseOperation() default close operation},
+ * the window maybe destroyed or not.
+ * </p>
+ * In case the window will be destroyed (see above), release of resources is recommended.
+ **/
public void windowDestroyNotify(WindowEvent e);
- /** Window has been destroyed.*/
+ /**
+ * Window has been destroyed.
+ */
public void windowDestroyed(WindowEvent e);
/** Window gained focus. */
diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
index 505939de2..9044517b5 100644
--- a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,20 +20,21 @@
* 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 com.jogamp.newt.event;
import javax.media.nativewindow.util.Rectangle;
+@SuppressWarnings("serial")
public class WindowUpdateEvent extends WindowEvent {
final Rectangle bounds;
- public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds)
+ public WindowUpdateEvent(short eventType, Object source, long when, Rectangle bounds)
{
super(eventType, source, when);
this.bounds = bounds;
@@ -43,7 +44,17 @@ public class WindowUpdateEvent extends WindowEvent {
return bounds;
}
+ @Override
public String toString() {
- return "WindowUpdateEvent["+super.toString()+", "+bounds+"]";
+ return toString(null).toString();
+ }
+
+ @Override
+ public StringBuilder toString(StringBuilder sb) {
+ if(null == sb) {
+ sb = new StringBuilder();
+ }
+ sb.append("WindowUpdateEvent[").append(bounds).append(", ");
+ return super.toString(sb).append("]");
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
index 8991203d5..864db1f7b 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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 com.jogamp.newt.event.awt;
import jogamp.newt.Debug;
@@ -48,10 +48,10 @@ import jogamp.newt.Debug;
* Common:<br>
* <pre>
// your demo/render code
- javax.media.opengl.GLEvenListener demo1 = new javax.media.opengl.GLEvenListener() { ... } ;
+ javax.media.opengl.GLEvenListener demo1 = new javax.media.opengl.GLEvenListener() { ... } ;
// your AWT agnostic NEWT mouse listener code
- com.jogamp.newt.event.MouseListener mouseListener = new com.jogamp.newt.event.MouseAdapter() { ... } ;
+ com.jogamp.newt.event.MouseListener mouseListener = new com.jogamp.newt.event.MouseAdapter() { ... } ;
* </pre> </p>
* <p>
* Default NEWT use case, without using the AWTAdapter:<br>
@@ -96,7 +96,7 @@ import jogamp.newt.Debug;
<br>
new AWTMouseAdapter(mouseListener, glWindow).addTo(comp);<br>
* </pre> </p>
- *
+ *
* Last but not least, the AWTAdapter maybe used as a general AWT event forwarder to NEWT.<br>
*
* <p>
@@ -108,7 +108,7 @@ import jogamp.newt.Debug;
<br>
new AWTMouseAdapter(glWindow).addTo(comp); // forward all AWT events to glWindow, as NEWT events<br>
* </pre> </p>
- *
+ *
* @see #attachTo
*/
public abstract class AWTAdapter implements java.util.EventListener
@@ -117,25 +117,29 @@ public abstract class AWTAdapter implements java.util.EventListener
com.jogamp.newt.event.NEWTEventListener newtListener;
com.jogamp.newt.Window newtWindow;
+ boolean consumeAWTEvent;
+ protected boolean isSetup;
- /**
+ /**
* Simply wrap aroung a NEWT EventListener, exposed as an AWT EventListener.<br>
* The NEWT EventListener will be called when an event happens.<br>
*/
- public AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener) {
+ protected AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener) {
if(null==newtListener) {
throw new RuntimeException("Argument newtListener is null");
}
this.newtListener = newtListener;
this.newtWindow = null;
+ this.consumeAWTEvent = false;
+ this.isSetup = true;
}
- /**
+ /**
* Wrap aroung a NEWT EventListener, exposed as an AWT EventListener,<br>
* where the given NEWT Window impersonates as the event's source.
* The NEWT EventListener will be called when an event happens.<br>
*/
- public AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener, com.jogamp.newt.Window newtProxy) {
+ protected AWTAdapter(com.jogamp.newt.event.NEWTEventListener newtListener, com.jogamp.newt.Window newtProxy) {
if(null==newtListener) {
throw new RuntimeException("Argument newtListener is null");
}
@@ -144,33 +148,65 @@ public abstract class AWTAdapter implements java.util.EventListener
}
this.newtListener = newtListener;
this.newtWindow = newtProxy;
+ this.consumeAWTEvent = false;
+ this.isSetup = true;
}
- /**
+ /**
* Create a pipeline adapter, AWT EventListener.<br>
* Once attached to an AWT component, it sends the converted AWT events to the NEWT downstream window.<br>
* This is only supported with EDT enabled!
*/
- public AWTAdapter(com.jogamp.newt.Window downstream) {
+ protected AWTAdapter(com.jogamp.newt.Window downstream) {
+ this();
+ setDownstream(downstream);
+ }
+
+ public AWTAdapter() {
+ clear();
+ this.consumeAWTEvent = false;
+ }
+
+ /**
+ * Setup a pipeline adapter, AWT EventListener.<br>
+ * Once attached to an AWT component, it sends the converted AWT events to the NEWT downstream window.<br>
+ * This is only supported with EDT enabled!
+ */
+ public synchronized AWTAdapter setDownstream(com.jogamp.newt.Window downstream) {
if(null==downstream) {
throw new RuntimeException("Argument downstream is null");
}
this.newtListener = null;
this.newtWindow = downstream;
+ this.consumeAWTEvent = false;
if( null == newtWindow.getScreen().getDisplay().getEDTUtil() ) {
throw new RuntimeException("EDT not enabled");
}
+ this.isSetup = true;
+ return this;
+ }
+
+ /** Removes all references, downstream and NEWT-EventListener. */
+ public synchronized AWTAdapter clear() {
+ this.newtListener = null;
+ this.newtWindow = null;
+ this.isSetup = false;
+ return this;
}
- public final com.jogamp.newt.Window getNewtWindow() {
- return newtWindow;
+ public final synchronized void setConsumeAWTEvent(boolean v) {
+ this.consumeAWTEvent = v;
}
-
- public final com.jogamp.newt.event.NEWTEventListener getNewtEventListener() {
- return newtListener;
+
+ public final synchronized com.jogamp.newt.Window getNewtWindow() {
+ return newtWindow;
+ }
+
+ public final synchronized com.jogamp.newt.event.NEWTEventListener getNewtEventListener() {
+ return newtListener;
}
-
- /**
+
+ /**
* Due to the fact that some NEWT {@link com.jogamp.newt.event.NEWTEventListener}
* are mapped to more than one {@link java.util.EventListener},
* this method is for your convenience to use this Adapter as a listener for all types.<br>
@@ -181,8 +217,13 @@ public abstract class AWTAdapter implements java.util.EventListener
/** @see #addTo(java.awt.Component) */
public abstract AWTAdapter removeFrom(java.awt.Component awtComponent);
+ /**
+ * Enqueues the event to the {@link #getNewtWindow()} is not null.
+ */
void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
- newtWindow.enqueueEvent(wait, event);
+ if( null != newtWindow ) {
+ newtWindow.enqueueEvent(wait, event);
+ }
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
index 7b0f6ba97..d4226f53e 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,16 +20,21 @@
* 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 com.jogamp.newt.event.awt;
import jogamp.newt.awt.event.AWTNewtEventFactory;
+/**
+ * AWT:
+ * printable: PRESSED (t0), TYPED (t0), RELEASED (t1)
+ * non-printable: PRESSED (t0), RELEASED (t1)
+ */
public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListener
{
public AWTKeyAdapter(com.jogamp.newt.event.KeyListener newtListener) {
@@ -44,18 +49,29 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
super(downstream);
}
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ public AWTKeyAdapter() {
+ super();
+ }
+
+ @Override
+ public synchronized AWTAdapter addTo(java.awt.Component awtComponent) {
awtComponent.addKeyListener(this);
return this;
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(java.awt.Component awtComponent) {
awtComponent.removeKeyListener(this);
return this;
}
- public void keyPressed(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
+ @Override
+ public synchronized void keyPressed(java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.KeyListener)newtListener).keyPressed(event);
} else {
@@ -63,8 +79,13 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
}
}
- public void keyReleased(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
+ @Override
+ public synchronized void keyReleased(java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.KeyListener)newtListener).keyReleased(event);
} else {
@@ -72,12 +93,11 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
}
}
- public void keyTyped(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow);
- if(null!=newtListener) {
- ((com.jogamp.newt.event.KeyListener)newtListener).keyTyped(event);
- } else {
- enqueueEvent(false, event);
+ @Override
+ public synchronized void keyTyped(java.awt.event.KeyEvent e) {
+ if( !isSetup ) { return; }
+ if( consumeAWTEvent ) {
+ e.consume();
}
}
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
index 115743a0d..8ad1fa6ab 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,17 +20,17 @@
* 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 com.jogamp.newt.event.awt;
import jogamp.newt.awt.event.AWTNewtEventFactory;
-public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseListener,
+public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseListener,
java.awt.event.MouseMotionListener,
java.awt.event.MouseWheelListener
{
@@ -46,22 +46,33 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
super(downstream);
}
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ public AWTMouseAdapter() {
+ super();
+ }
+
+ @Override
+ public synchronized AWTAdapter addTo(java.awt.Component awtComponent) {
awtComponent.addMouseListener(this);
awtComponent.addMouseMotionListener(this);
awtComponent.addMouseWheelListener(this);
return this;
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(java.awt.Component awtComponent) {
awtComponent.removeMouseListener(this);
awtComponent.removeMouseMotionListener(this);
awtComponent.removeMouseWheelListener(this);
return this;
}
- public void mouseClicked(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseClicked(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseClicked(event);
} else {
@@ -69,8 +80,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseEntered(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseEntered(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseEntered(event);
} else {
@@ -78,8 +94,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseExited(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseExited(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseExited(event);
} else {
@@ -87,8 +108,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mousePressed(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mousePressed(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mousePressed(event);
} else {
@@ -96,8 +122,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseReleased(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseReleased(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseReleased(event);
} else {
@@ -105,8 +136,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseDragged(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseDragged(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseDragged(event);
} else {
@@ -114,8 +150,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseMoved(java.awt.event.MouseEvent e) {
+ @Override
+ public synchronized void mouseMoved(java.awt.event.MouseEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseMoved(event);
} else {
@@ -123,8 +164,13 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL
}
}
- public void mouseWheelMoved(java.awt.event.MouseWheelEvent e) {
+ @Override
+ public synchronized void mouseWheelMoved(java.awt.event.MouseWheelEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow);
+ if( consumeAWTEvent ) {
+ e.consume();
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.MouseListener)newtListener).mouseWheelMoved(event);
} else {
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
index 69b0d0482..2e5527ee1 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,18 +20,20 @@
* 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 com.jogamp.newt.event.awt;
+import java.awt.Dimension;
+
import jogamp.newt.awt.event.AWTNewtEventFactory;
-public class AWTWindowAdapter
- extends AWTAdapter
+public class AWTWindowAdapter
+ extends AWTAdapter
implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.FocusListener
{
WindowClosingListener windowClosingListener;
@@ -47,15 +49,17 @@ public class AWTWindowAdapter
public AWTWindowAdapter(com.jogamp.newt.Window downstream) {
super(downstream);
}
+ public AWTWindowAdapter() {
+ super();
+ }
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter addTo(java.awt.Component awtComponent) {
java.awt.Window win = getWindow(awtComponent);
awtComponent.addComponentListener(this);
awtComponent.addFocusListener(this);
- if( null == windowClosingListener ) {
+ if( null != win && null == windowClosingListener ) {
windowClosingListener = new WindowClosingListener();
- }
- if( null != win ) {
win.addWindowListener(windowClosingListener);
}
if(awtComponent instanceof java.awt.Window) {
@@ -64,13 +68,19 @@ public class AWTWindowAdapter
return this;
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
- awtComponent.removeFocusListener(this);
- awtComponent.removeComponentListener(this);
+ public synchronized AWTAdapter removeWindowClosingFrom(java.awt.Component awtComponent) {
java.awt.Window win = getWindow(awtComponent);
if( null != win && null != windowClosingListener ) {
win.removeWindowListener(windowClosingListener);
}
+ return this;
+ }
+
+ @Override
+ public synchronized AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ awtComponent.removeFocusListener(this);
+ awtComponent.removeComponentListener(this);
+ removeWindowClosingFrom(awtComponent);
if(awtComponent instanceof java.awt.Window) {
((java.awt.Window)awtComponent).removeWindowListener(this);
}
@@ -87,8 +97,13 @@ public class AWTWindowAdapter
return null;
}
- public void focusGained(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusGained(java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWT: focusGained: "+e+" -> "+event);
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event);
} else {
@@ -96,8 +111,13 @@ public class AWTWindowAdapter
}
}
- public void focusLost(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusLost(java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWT: focusLost: "+e+" -> "+event);
+ }
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event);
} else {
@@ -105,10 +125,24 @@ public class AWTWindowAdapter
}
}
- public void componentResized(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentResized(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: componentResized: "+event);
+ final java.awt.Component c = e.getComponent();
+ final java.awt.Dimension sz = c.getSize();
+ final java.awt.Insets insets;
+ final java.awt.Dimension sz2;
+ if(c instanceof java.awt.Container) {
+ insets = ((java.awt.Container)c).getInsets();
+ sz2 = new Dimension(sz.width - insets.left - insets.right,
+ sz.height - insets.top - insets.bottom);
+ } else {
+ insets = null;
+ sz2 = sz;
+ }
+ System.err.println("AWT: componentResized: "+sz+" ( "+insets+", "+sz2+" ), "+e+" -> "+event);
}
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowResized(event);
@@ -117,10 +151,12 @@ public class AWTWindowAdapter
}
}
- public void componentMoved(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentMoved(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: componentMoved: "+event);
+ System.err.println("AWT: componentMoved: "+e+" -> "+event);
}
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowMoved(event);
@@ -129,7 +165,9 @@ public class AWTWindowAdapter
}
}
- public void componentShown(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentShown(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentShown: "+comp);
@@ -146,7 +184,9 @@ public class AWTWindowAdapter
}*/
}
- public void componentHidden(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentHidden(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentHidden: "+comp);
@@ -163,7 +203,9 @@ public class AWTWindowAdapter
}*/
}
- public void windowActivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowActivated(java.awt.event.WindowEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event);
@@ -172,11 +214,15 @@ public class AWTWindowAdapter
}
}
- public void windowClosed(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowClosed(java.awt.event.WindowEvent e) { }
- public void windowClosing(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowClosing(java.awt.event.WindowEvent e) { }
- public void windowDeactivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowDeactivated(java.awt.event.WindowEvent e) {
+ if( !isSetup ) { return; }
com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
if(null!=newtListener) {
((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event);
@@ -185,27 +231,50 @@ public class AWTWindowAdapter
}
}
- public void windowDeiconified(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowDeiconified(java.awt.event.WindowEvent e) { }
- public void windowIconified(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowIconified(java.awt.event.WindowEvent e) { }
- public void windowOpened(java.awt.event.WindowEvent e) { }
+ @Override
+ public synchronized void windowOpened(java.awt.event.WindowEvent e) { }
class WindowClosingListener implements java.awt.event.WindowListener {
+ @Override
public void windowClosing(java.awt.event.WindowEvent e) {
- com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
- if(null!=newtListener) {
- ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event);
- } else {
- enqueueEvent(true, event);
+ synchronized( AWTWindowAdapter.this ) {
+ if( !isSetup ) { return; }
+ com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ if(null!=newtListener) {
+ ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event);
+ } else {
+ enqueueEvent(true, event);
+ }
+ }
+ }
+ @Override
+ public void windowClosed(java.awt.event.WindowEvent e) {
+ synchronized( AWTWindowAdapter.this ) {
+ if( !isSetup ) { return; }
+ com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow);
+ if(null!=newtListener) {
+ ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyed(event);
+ } else {
+ enqueueEvent(true, event);
+ }
}
}
+ @Override
public void windowActivated(java.awt.event.WindowEvent e) { }
- public void windowClosed(java.awt.event.WindowEvent e) { }
+ @Override
public void windowDeactivated(java.awt.event.WindowEvent e) { }
+ @Override
public void windowDeiconified(java.awt.event.WindowEvent e) { }
+ @Override
public void windowIconified(java.awt.event.WindowEvent e) { }
+ @Override
public void windowOpened(java.awt.event.WindowEvent e) { }
}
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index f89193754..4b740927b 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,105 +29,127 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package com.jogamp.newt.opengl;
-import java.io.PrintStream;
-
-import com.jogamp.common.GlueGenVersion;
-import com.jogamp.common.util.VersionUtil;
-import com.jogamp.newt.*;
-import com.jogamp.newt.event.*;
-
-import jogamp.newt.WindowImpl;
-
-import javax.media.nativewindow.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+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.SurfaceUpdatedListener;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
-import javax.media.opengl.*;
+import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL4ES3;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLES3;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
-import jogamp.opengl.FPSCounterImpl;
-import jogamp.opengl.GLDrawableHelper;
+import jogamp.newt.WindowImpl;
+import jogamp.opengl.GLAutoDrawableBase;
+import jogamp.opengl.GLContextImpl;
+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.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.NEWTEvent;
+import com.jogamp.newt.event.NEWTEventConsumer;
+import com.jogamp.newt.event.NEWTEventListener;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.opengl.JoglVersion;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLStateKeeper;
/**
* An implementation of {@link GLAutoDrawable} and {@link Window} interface,
* using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed).
* <P>
+ * This implementation supports {@link GLStateKeeper GL state preservation},
+ * hence {@link #isGLStatePreservationSupported()} returns <code>true</code>.
+ * </P>
+ * <P>
* This implementation does not make the OpenGL context current<br>
- * before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br>
+ * before calling the various input EventListener callbacks, ie {@link MouseListener} etc.<br>
* This design decision is made in favor of a more performant and simplified
* implementation. Also the event dispatcher shall be implemented OpenGL agnostic.<br>
- * To be able to use OpenGL commands from within such input {@link com.jogamp.newt.event.NEWTEventListener},<br>
- * you can inject {@link javax.media.opengl.GLRunnable} objects
- * via {@link #invoke(boolean, javax.media.opengl.GLRunnable)} to the OpenGL command stream.<br>
- * <p>
+ * To be able to use OpenGL commands from within such input {@link NEWTEventListener},<br>
+ * you can inject {@link GLRunnable} objects
+ * via {@link #invoke(boolean, GLRunnable)} to the OpenGL command stream.<br>
+ * </p>
*/
-public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter {
+public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter {
private final WindowImpl window;
/**
* Constructor. Do not call this directly -- use {@link #create()} instead.
*/
protected GLWindow(Window window) {
- resetFPSCounter();
+ super(null, null, false /* always handle device lifecycle ourselves */);
this.window = (WindowImpl) window;
- ((WindowImpl)this.window).setHandleDestroyNotify(false);
+ this.window.setWindowDestroyNotifyAction( new Runnable() {
+ @Override
+ public void run() {
+ defaultWindowDestroyNotifyOp();
+ } } );
window.addWindowListener(new WindowAdapter() {
@Override
public void windowRepaint(WindowUpdateEvent e) {
- if( !GLWindow.this.window.isWindowLockedByOtherThread() && !GLWindow.this.helper.isAnimatorAnimating() ) {
- display();
- }
+ defaultWindowRepaintOp();
}
@Override
public void windowResized(WindowEvent e) {
- sendReshape = true;
- if( !GLWindow.this.window.isWindowLockedByOtherThread() && !GLWindow.this.helper.isAnimatorAnimating() ) {
- display();
- }
+ defaultWindowResizedOp(getWidth(), getHeight());
}
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- if( WindowClosingMode.DISPOSE_ON_CLOSE == GLWindow.this.getDefaultCloseOperation() ) {
- // Is an animator thread perform rendering?
- if (GLWindow.this.helper.isExternalAnimatorRunning()) {
- // Pause animations before initiating safe destroy.
- GLAnimatorControl ctrl = GLWindow.this.helper.getAnimator();
- boolean isPaused = ctrl.pause();
- destroy();
- if(isPaused) {
- ctrl.resume();
- }
- } else if (GLWindow.this.window.isWindowLockedByOtherThread()) {
- // Window is locked by another thread
- // Flag that destroy should be performed on the next
- // attempt to display.
- sendDestroy = true;
- } else {
- // Without an external thread animating or locking the
- // surface, we are safe.
- destroy ();
- }
- }
- }
});
this.window.setLifecycleHook(new GLLifecycleHook());
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return window;
+ }
+
/**
- * Creates a new GLWindow attaching a new Window referencing a
+ * Creates a new GLWindow attaching a new Window referencing a
* new default Screen and default Display with the given GLCapabilities.
* <p>
* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()}
* and {@link Screen#removeReference()}.
* </p>
- * The default Display will be reused if already instantiated.
+ * The default Display will be reused if already instantiated.
*/
public static GLWindow create(GLCapabilitiesImmutable caps) {
return new GLWindow(NewtFactory.createWindow(caps));
@@ -145,7 +167,7 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
return new GLWindow(NewtFactory.createWindow(screen, caps));
}
- /**
+ /**
* Creates a new GLWindow attaching the given window.
* <p>
* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()}
@@ -156,13 +178,13 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
return new GLWindow(window);
}
- /**
- * Creates a new GLWindow attaching a new child Window
+ /**
+ * Creates a new GLWindow attaching a new child Window
* of the given <code>parentNativeWindow</code> with the given GLCapabilities.
* <p>
* The Display/Screen will be compatible with the <code>parentNativeWindow</code>,
* or even identical in case it's a Newt Window.
- * An already instantiated compatible Display will be reused.
+ * An already instantiated compatible Display will be reused.
* </p>
* <p>
* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()}
@@ -176,10 +198,12 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
//----------------------------------------------------------------------
// WindowClosingProtocol implementation
//
+ @Override
public WindowClosingMode getDefaultCloseOperation() {
return window.getDefaultCloseOperation();
}
+ @Override
public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
return window.setDefaultCloseOperation(op);
}
@@ -188,165 +212,255 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
// Window Access
//
+ @Override
public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
return window.setCapabilitiesChooser(chooser);
}
+ @Override
public final CapabilitiesImmutable getChosenCapabilities() {
- if (drawable == null) {
- return window.getChosenCapabilities();
- }
-
- return drawable.getChosenGLCapabilities();
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities();
}
+ @Override
public final CapabilitiesImmutable getRequestedCapabilities() {
return window.getRequestedCapabilities();
}
+ @Override
public final Window getDelegatedWindow() {
return window.getDelegatedWindow();
}
+ @Override
public final NativeWindow getParent() {
return window.getParent();
}
+ @Override
public final Screen getScreen() {
return window.getScreen();
}
+ @Override
+ public final MonitorDevice getMainMonitor() {
+ return window.getMainMonitor();
+ }
+
+ @Override
public final void setTitle(String title) {
window.setTitle(title);
}
+ @Override
public final String getTitle() {
return window.getTitle();
}
+ @Override
public final boolean isPointerVisible() {
return window.isPointerVisible();
}
-
+
+ @Override
public final void setPointerVisible(boolean mouseVisible) {
- window.setPointerVisible(mouseVisible);
+ window.setPointerVisible(mouseVisible);
+ }
+
+ @Override
+ public final PointerIcon getPointerIcon() {
+ return window.getPointerIcon();
+ }
+
+ @Override
+ public final void setPointerIcon(final PointerIcon pi) {
+ window.setPointerIcon(pi);
}
-
+
+ @Override
public final boolean isPointerConfined() {
return window.isPointerConfined();
}
-
+
+ @Override
public final void confinePointer(boolean grab) {
window.confinePointer(grab);
}
-
+
+ @Override
public final void setUndecorated(boolean value) {
window.setUndecorated(value);
}
+ @Override
public final void warpPointer(int x, int y) {
window.warpPointer(x, y);
}
+ @Override
public final boolean isUndecorated() {
return window.isUndecorated();
}
+ @Override
public final void setAlwaysOnTop(boolean value) {
window.setAlwaysOnTop(value);
}
-
+
+ @Override
public final boolean isAlwaysOnTop() {
return window.isAlwaysOnTop();
}
-
+
+ @Override
public final void setFocusAction(FocusRunnable focusAction) {
window.setFocusAction(focusAction);
}
-
+
+ @Override
public void setKeyboardFocusHandler(KeyListener l) {
window.setKeyboardFocusHandler(l);
}
-
+
+ @Override
public final void requestFocus() {
window.requestFocus();
}
+ @Override
public final void requestFocus(boolean wait) {
- window.requestFocus(wait);
+ window.requestFocus(wait);
}
-
+
+ @Override
public boolean hasFocus() {
return window.hasFocus();
}
- public final InsetsImmutable getInsets() {
+ @Override
+ public final InsetsImmutable getInsets() {
return window.getInsets();
}
-
+
+ @Override
+ public final int getX() {
+ return window.getX();
+ }
+
+ @Override
+ public final int getY() {
+ return window.getY();
+ }
+
+ @Override
+ public final int getWidth() {
+ return window.getWidth();
+ }
+
+ @Override
+ public final int getHeight() {
+ return window.getHeight();
+ }
+
+ @Override
public final void setPosition(int x, int y) {
window.setPosition(x, y);
}
- public void setTopLevelPosition(int x, int y) {
+ @Override
+ public void setTopLevelPosition(int x, int y) {
window.setTopLevelPosition(x, y);
}
+ @Override
public final boolean setFullscreen(boolean fullscreen) {
return window.setFullscreen(fullscreen);
}
+ @Override
+ public boolean setFullscreen(List<MonitorDevice> monitors) {
+ return window.setFullscreen(monitors);
+ }
+
+ @Override
public final boolean isFullscreen() {
return window.isFullscreen();
}
+ @Override
public final boolean isVisible() {
return window.isVisible();
}
@Override
public final String toString() {
- return "NEWT-GLWindow[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable +
+ return "NEWT-GLWindow[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable +
", \n\tContext: " + context + ", \n\tWindow: "+window+ /** ", \n\tFactory: "+factory+ */ "]";
}
+ @Override
public final ReparentOperation reparentWindow(NativeWindow newParent) {
return window.reparentWindow(newParent);
}
- public final ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) {
- return window.reparentWindow(newParent, forceDestroyCreate);
+ @Override
+ public final ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, boolean forceDestroyCreate) {
+ return window.reparentWindow(newParent, x, y, forceDestroyCreate);
+ }
+
+ @Override
+ public final ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints) {
+ return window.reparentWindow(newParent, x, y, hints);
}
+ @Override
public final boolean removeChild(NativeWindow win) {
return window.removeChild(win);
}
+ @Override
public final boolean addChild(NativeWindow win) {
return window.addChild(win);
}
-
+
//----------------------------------------------------------------------
// Window.LifecycleHook Implementation
//
+ @Override
public final void destroy() {
window.destroy();
}
+ @Override
+ public void setWindowDestroyNotifyAction(Runnable r) {
+ window.setWindowDestroyNotifyAction(r);
+ }
+
+ @Override
public final void setVisible(boolean visible) {
window.setVisible(visible);
}
+ @Override
+ public void setVisible(boolean wait, boolean visible) {
+ window.setVisible(wait, visible);
+ }
+
+ @Override
public final void setSize(int width, int height) {
window.setSize(width, height);
}
+ @Override
public void setTopLevelSize(int width, int height) {
- window.setTopLevelSize(width, height);
+ window.setTopLevelSize(width, height);
}
-
+
+ @Override
public final boolean isNativeValid() {
return window.isNativeValid();
}
+ @Override
public Point getLocationOnScreen(Point storage) {
return window.getLocationOnScreen(storage);
}
@@ -354,82 +468,86 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
// Hide methods here ..
protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
+ @Override
+ public void preserveGLStateAtDestroy(boolean value) {
+ GLWindow.this.preserveGLStateAtDestroy(value);
+ }
+
+ @Override
public synchronized void destroyActionPreLock() {
// nop
}
+ @Override
public synchronized void destroyActionInLock() {
if(Window.DEBUG_IMPLEMENTATION) {
- String msg = "GLWindow.destroy() "+Thread.currentThread()+", start";
+ String msg = "GLWindow.destroy() "+WindowImpl.getThreadName()+", start";
System.err.println(msg);
//Exception e1 = new Exception(msg);
//e1.printStackTrace();
}
- if( window.isNativeValid() && null != drawable && drawable.isRealized() ) {
- if( null != context && context.isCreated() ) {
- // Catch dispose GLExceptions by GLEventListener, just 'print' them
- // so we can continue with the destruction.
- try {
- helper.disposeGL(GLWindow.this, drawable, context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
- }
- }
- drawable.setRealized(false);
- }
- context = null;
- drawable = null;
-
+ destroyImplInLock();
+
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.destroy() "+Thread.currentThread()+", fin");
+ System.err.println("GLWindow.destroy() "+WindowImpl.getThreadName()+", fin");
}
}
+ @Override
public synchronized void resetCounter() {
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.resetCounter() "+Thread.currentThread());
+ System.err.println("GLWindow.resetCounter() "+WindowImpl.getThreadName());
}
GLWindow.this.resetFPSCounter();
+ final GLAnimatorControl animator = GLWindow.this.getAnimator();
+ if( null != animator ) {
+ animator.resetFPSCounter();
+ }
}
+ @Override
public synchronized void setVisibleActionPost(boolean visible, boolean nativeWindowCreated) {
long t0;
if(Window.DEBUG_IMPLEMENTATION) {
t0 = System.nanoTime();
- System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", start");
+ System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", start");
} else {
t0 = 0;
}
- /* if (nativeWindowCreated && null != context) {
- throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
- } */
- if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
- NativeWindow nw;
- if (window.getWrappedWindow() != null) {
- nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getPrivateGraphicsConfiguration());
- } else {
- nw = window;
- }
- GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getChosenCapabilities();
- if(null==factory) {
- factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
+ if (null == drawable && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) {
+ if( ( null != context ) ) {
+ throw new InternalError("GLWindow.LifecycleHook.setVisiblePost: "+WindowImpl.getThreadName()+" - Null drawable, but valid context - "+GLWindow.this);
}
- if(null==drawable) {
- drawable = factory.createGLDrawable(nw);
+ final GLContext[] shareWith = { null };
+ if( !helper.isSharedGLContextPending(shareWith) ) {
+ final NativeSurface ns;
+ {
+ final NativeSurface wrapped_ns = window.getWrappedSurface();
+ ns = null != wrapped_ns ? wrapped_ns : window;
+ }
+ final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) ns.getGraphicsConfiguration().getChosenCapabilities();
+ if(null==factory) {
+ factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
+ }
+ drawable = (GLDrawableImpl) factory.createGLDrawable(ns);
+ drawable.setRealized(true);
+
+ if( !GLWindow.this.restoreGLEventListenerState() ) {
+ context = (GLContextImpl) drawable.createContext(shareWith[0]);
+ context.setContextCreationFlags(additionalCtxCreationFlags);
+ }
}
- drawable.setRealized(true);
- context = drawable.createContext(sharedContext);
- context.setContextCreationFlags(additionalCtxCreationFlags);
}
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+Thread.currentThread()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+ System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", fin: dt "+ (System.nanoTime()-t0)/1e6 +"ms");
}
}
-
+
private GLAnimatorControl savedAnimator = null;
-
+
+ @Override
public synchronized boolean pauseRenderingAction() {
boolean animatorPaused = false;
savedAnimator = GLWindow.this.getAnimator();
@@ -439,302 +557,109 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
return animatorPaused;
}
+ @Override
public synchronized void resumeRenderingAction() {
if ( null != savedAnimator && savedAnimator.isPaused() ) {
savedAnimator.resume();
}
}
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void shutdownRenderingAction() {
+ final GLAnimatorControl anim = GLWindow.this.getAnimator();
+ if ( null != anim && anim.isAnimating() ) {
+ final Thread animThread = anim.getThread();
+ if( animThread == Thread.currentThread() ) {
+ anim.stop(); // on anim thread, non-blocking
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ if( anim.isAnimating() && null != animThread ) {
+ try {
+ animThread.stop();
+ } catch(Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ }
+ return null;
+ } } );
+ }
+ }
+ }
}
//----------------------------------------------------------------------
// OpenGL-related methods and state
//
- private GLContext sharedContext = null;
- private int additionalCtxCreationFlags = 0;
- private GLDrawableFactory factory;
- private GLDrawable drawable;
- private GLContext context;
- private GLDrawableHelper helper = new GLDrawableHelper();
- // To make reshape events be sent immediately before a display event
- private boolean sendReshape=false;
- private boolean sendDestroy=false;
- private FPSCounterImpl fpsCounter = new FPSCounterImpl();
-
- public GLDrawableFactory getFactory() {
- return factory;
- }
-
- /**
- * Specifies an {@link javax.media.opengl.GLContext OpenGL context} to share with.<br>
- * At native creation, {@link #setVisible(boolean) setVisible(true)},
- * a {@link javax.media.opengl.GLDrawable drawable} and {@link javax.media.opengl.GLContext context} is created besides the native Window itself,<br>
- * hence you shall set the shared context before.
- *
- * @param sharedContext The OpenGL context shared by this GLWindow's one
- */
- public void setSharedContext(GLContext sharedContext) {
- this.sharedContext = sharedContext;
- }
-
- public void setContext(GLContext newCtx) {
- context = newCtx;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
- }
- }
-
- public GLContext getContext() {
- return context;
- }
-
- public GL getGL() {
- if (context == null) {
- return null;
- }
- return context.getGL();
- }
-
- public GL setGL(GL gl) {
- if (context != null) {
- context.setGL(gl);
- return gl;
- }
- return null;
- }
-
- public void addGLEventListener(GLEventListener listener) {
- if(null!=helper) {
- helper.addGLEventListener(listener);
- }
- }
-
- public void addGLEventListener(int index, GLEventListener listener) {
- if(null!=helper) {
- helper.addGLEventListener(index, listener);
- }
- }
-
- public void removeGLEventListener(GLEventListener listener) {
- if(null!=helper) {
- helper.removeGLEventListener(listener);
- }
- }
-
- public void setAnimator(GLAnimatorControl animatorControl) {
- if(null!=helper) {
- helper.setAnimator(animatorControl);
- }
- }
-
- public GLAnimatorControl getAnimator() {
- if(null!=helper) {
- return helper.getAnimator();
- }
- return null;
- }
-
- public void invoke(boolean wait, GLRunnable glRunnable) {
- if(null!=helper) {
- helper.invoke(this, wait, glRunnable);
- }
+ @Override
+ protected final RecursiveLock getLock() {
+ return window.getLock();
}
+ @Override
public void display() {
if( !isNativeValid() || !isVisible() ) { return; }
-
+
if(sendDestroy || ( window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) {
sendDestroy=false;
destroy();
return;
}
-
- if( null == context && 0<getWidth()*getHeight() ) { // TODO: Check memory sync
- // retry drawable and context creation
- setVisible(true);
- }
- if( null != context ) { // TODO: Check memory sync
- // surface is locked/unlocked implicit by context's makeCurrent/release
- helper.invokeGL(drawable, context, displayAction, initAction);
- }
- }
-
- public void setAutoSwapBufferMode(boolean enable) {
- if(null!=helper) {
- helper.setAutoSwapBufferMode(enable);
- }
- }
-
- public boolean getAutoSwapBufferMode() {
- if(null!=helper) {
- return helper.getAutoSwapBufferMode();
+ final boolean done;
+ final RecursiveLock lock = window.getLock();
+ lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating
+ try {
+ if( null != context ) {
+ // surface is locked/unlocked implicit by context's makeCurrent/release
+ helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
+ done = true;
+ } else {
+ done = false;
+ }
+ } finally {
+ lock.unlock();
}
- return false;
- }
-
- /**
- * @param t the thread for which context release shall be skipped, usually the animation thread,
- * ie. {@link Animator#getThread()}.
- * @deprecated this is an experimental feature,
- * intended for measuring performance in regards to GL context switch
- */
- public void setSkipContextReleaseThread(Thread t) {
- if(null!=helper) {
- helper.setSkipContextReleaseThread(t);
+ if( !done && ( 0 < getWidth() && 0 < getHeight() ) ) {
+ // retry drawable and context creation, will itself issue resize -> display
+ setVisible(true);
}
}
/**
- * @deprecated see {@link #setSkipContextReleaseThread(Thread)}
+ * {@inheritDoc}
+ * <p>
+ * GLWindow supports GL state preservation, hence returns <code>true</code>.
+ * </p>
*/
- public Thread getSkipContextReleaseThread() {
- if(null!=helper) {
- return helper.getSkipContextReleaseThread();
- }
- return null;
- }
-
- public void swapBuffers() {
- if(drawable!=null && context != null) {
- drawable.swapBuffers();
- }
- }
-
- public void setContextCreationFlags(int flags) {
- additionalCtxCreationFlags = flags;
- }
-
- public int getContextCreationFlags() {
- return additionalCtxCreationFlags;
- }
-
- private class InitAction implements Runnable {
- public final void run() {
- // Lock: Locked Surface/Window by MakeCurrent/Release
- helper.init(GLWindow.this);
- resetFPSCounter();
- }
- }
- private InitAction initAction = new InitAction();
-
- private class DisplayAction implements Runnable {
- public final void run() {
- // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release
- if (sendReshape) {
- helper.reshape(GLWindow.this, 0, 0, getWidth(), getHeight());
- sendReshape = false;
- }
-
- helper.display(GLWindow.this);
-
- fpsCounter.tickFPS();
- }
- }
- private DisplayAction displayAction = new DisplayAction();
-
- public final void setUpdateFPSFrames(int frames, PrintStream out) {
- fpsCounter.setUpdateFPSFrames(frames, out);
- }
-
- public final void resetFPSCounter() {
- fpsCounter.resetFPSCounter();
- }
-
- public final int getUpdateFPSFrames() {
- return fpsCounter.getUpdateFPSFrames();
- }
-
- public final long getFPSStartTime() {
- return fpsCounter.getFPSStartTime();
- }
-
- public final long getLastFPSUpdateTime() {
- return fpsCounter.getLastFPSUpdateTime();
- }
-
- public final long getLastFPSPeriod() {
- return fpsCounter.getLastFPSPeriod();
- }
-
- public final float getLastFPS() {
- return fpsCounter.getLastFPS();
- }
-
- public final int getTotalFPSFrames() {
- return fpsCounter.getTotalFPSFrames();
- }
-
- public final long getTotalFPSDuration() {
- return fpsCounter.getTotalFPSDuration();
- }
-
- public final float getTotalFPS() {
- return fpsCounter.getTotalFPS();
- }
+ @Override
+ public final boolean isGLStatePreservationSupported() { return true; }
//----------------------------------------------------------------------
// GLDrawable methods
//
+ private GLDrawableFactory factory;
- public final NativeSurface getNativeSurface() {
- return null!=drawable ? drawable.getNativeSurface() : null;
- }
-
- public final long getHandle() {
- return null!=drawable ? drawable.getHandle() : 0;
- }
-
- public final int getX() {
- return window.getX();
- }
-
- public final int getY() {
- return window.getY();
- }
-
- public final int getWidth() {
- return window.getWidth();
- }
-
- public final int getHeight() {
- return window.getHeight();
- }
-
- //----------------------------------------------------------------------
- // GLDrawable methods that are not really needed
- //
-
- public final GLContext createContext(GLContext shareWith) {
- return drawable.createContext(shareWith);
- }
-
- public final void setRealized(boolean realized) {
- }
-
- public final boolean isRealized() {
- return ( null != drawable ) ? drawable.isRealized() : false;
- }
-
- public final GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (drawable == null) {
- throw new GLException("No drawable yet");
- }
-
- return drawable.getChosenGLCapabilities();
+ @Override
+ public final GLDrawableFactory getFactory() {
+ return factory;
}
- public final GLProfile getGLProfile() {
- if (drawable == null) {
- throw new GLException("No drawable yet");
- }
-
- return drawable.getGLProfile();
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
}
//----------------------------------------------------------------------
- // NEWTEventConsumer
+ // NEWTEventConsumer
//
+ @Override
public boolean consumeEvent(NEWTEvent event) {
return window.consumeEvent(event);
}
@@ -742,179 +667,316 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC
//----------------------------------------------------------------------
// Window completion
//
+ @Override
public final void windowRepaint(int x, int y, int width, int height) {
window.windowRepaint(x, y, width, height);
}
+ @Override
public final void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
window.enqueueEvent(wait, event);
}
+ @Override
public final void runOnEDTIfAvail(boolean wait, final Runnable task) {
window.runOnEDTIfAvail(wait, task);
}
- public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.removeSurfaceUpdatedListener(l);
- }
-
- public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- window.addSurfaceUpdatedListener(l);
- }
-
- public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- window.addSurfaceUpdatedListener(index, l);
- }
-
+ @Override
public void sendWindowEvent(int eventType) {
window.sendWindowEvent(eventType);
}
+ @Override
public final WindowListener getWindowListener(int index) {
return window.getWindowListener(index);
}
+ @Override
public final WindowListener[] getWindowListeners() {
return window.getWindowListeners();
}
+ @Override
public final void removeWindowListener(WindowListener l) {
window.removeWindowListener(l);
}
+ @Override
public final void addWindowListener(WindowListener l) {
window.addWindowListener(l);
}
+ @Override
public final void addWindowListener(int index, WindowListener l) throws IndexOutOfBoundsException {
window.addWindowListener(index, l);
}
+ @Override
+ public final void setKeyboardVisible(boolean visible) {
+ window.setKeyboardVisible(visible);
+ }
+
+ @Override
+ public final boolean isKeyboardVisible() {
+ return window.isKeyboardVisible();
+ }
+
+ @Override
public final void addKeyListener(KeyListener l) {
window.addKeyListener(l);
}
+ @Override
public final void addKeyListener(int index, KeyListener l) {
window.addKeyListener(index, l);
}
+ @Override
public final void removeKeyListener(KeyListener l) {
window.removeKeyListener(l);
}
+ @Override
public final KeyListener getKeyListener(int index) {
return window.getKeyListener(index);
}
+ @Override
public final KeyListener[] getKeyListeners() {
return window.getKeyListeners();
}
+ @Override
public final void addMouseListener(MouseListener l) {
window.addMouseListener(l);
}
+ @Override
public final void addMouseListener(int index, MouseListener l) {
window.addMouseListener(index, l);
}
+ @Override
public final void removeMouseListener(MouseListener l) {
window.removeMouseListener(l);
}
+ @Override
public final MouseListener getMouseListener(int index) {
return window.getMouseListener(index);
}
+ @Override
public final MouseListener[] getMouseListeners() {
return window.getMouseListeners();
}
+ @Override
+ public void setDefaultGesturesEnabled(boolean enable) {
+ window.setDefaultGesturesEnabled(enable);
+ }
+ @Override
+ public boolean areDefaultGesturesEnabled() {
+ return window.areDefaultGesturesEnabled();
+ }
+ @Override
+ public final void addGestureHandler(GestureHandler gh) {
+ window.addGestureHandler(gh);
+ }
+ @Override
+ public final void addGestureHandler(int index, GestureHandler gh) {
+ window.addGestureHandler(index, gh);
+ }
+ @Override
+ public final void removeGestureHandler(GestureHandler gh) {
+ window.removeGestureHandler(gh);
+ }
+ @Override
+ public final void addGestureListener(GestureHandler.GestureListener gl) {
+ window.addGestureListener(-1, gl);
+ }
+ @Override
+ public final void addGestureListener(int index, GestureHandler.GestureListener gl) {
+ window.addGestureListener(index, gl);
+ }
+ @Override
+ public final void removeGestureListener(GestureHandler.GestureListener gl) {
+ window.removeGestureListener(gl);
+ }
+
//----------------------------------------------------------------------
// NativeWindow completion
//
- public final int lockSurface() {
+ @Override
+ public final int lockSurface() throws NativeWindowException, RuntimeException {
return window.lockSurface();
}
- public final void unlockSurface() throws NativeWindowException {
+ @Override
+ public final void unlockSurface() {
window.unlockSurface();
}
+ @Override
public final boolean isSurfaceLockedByOtherThread() {
return window.isSurfaceLockedByOtherThread();
}
- public final boolean isSurfaceLocked() {
- return window.isSurfaceLocked();
- }
-
+ @Override
public final Thread getSurfaceLockOwner() {
return window.getSurfaceLockOwner();
}
+ @Override
public final boolean surfaceSwap() {
return window.surfaceSwap();
}
+ @Override
+ public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ window.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ window.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ window.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ window.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
public final long getWindowHandle() {
return window.getWindowHandle();
}
+ @Override
public final long getSurfaceHandle() {
return window.getSurfaceHandle();
}
+ @Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
return window.getGraphicsConfiguration();
}
+ @Override
public final long getDisplayHandle() {
return window.getDisplayHandle();
}
+ @Override
public final int getScreenIndex() {
return window.getScreenIndex();
}
- public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- window.surfaceUpdated(updater, ns, when);
- }
-
/**
* A most simple JOGL AWT test entry
*/
public static void main(String args[]) {
+ final boolean forceES2;
+ final boolean forceES3;
+ final boolean forceGL3;
+ final boolean forceGL4ES3;
+ {
+ boolean _forceES2 = false;
+ boolean _forceES3 = false;
+ boolean _forceGL3 = false;
+ boolean _forceGL4ES3 = false;
+ if( null != args ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-es2")) {
+ _forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ _forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ _forceGL3 = true;
+ } else if(args[i].equals("-gl4es3")) {
+ _forceGL4ES3 = true;
+ }
+ }
+ }
+ forceES2 = _forceES2;
+ forceES3 = _forceES3;
+ forceGL3 = _forceGL3;
+ forceGL4ES3 = _forceGL4ES3;
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGL4ES3 "+forceGL4ES3);
+
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null).toString());
-
- final GLProfile glp = GLProfile.getDefault();
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
+
+ final GLProfile glp;
+ if(forceGL4ES3) {
+ glp = GLProfile.get(GLProfile.GL4ES3);
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getDefault();
+ }
final GLCapabilitiesImmutable caps = new GLCapabilities( glp );
+ System.err.println("Requesting: "+caps);
GLWindow glWindow = GLWindow.create(caps);
glWindow.setSize(128, 128);
glWindow.addGLEventListener(new GLEventListener() {
+ @Override
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
System.err.println(JoglVersion.getGLInfo(gl, null));
System.err.println("Requested: "+drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
System.err.println("Chosen : "+drawable.getChosenGLCapabilities());
+ System.err.println("GL impl. class "+gl.getClass().getName());
+ if( gl.isGL4ES3() ) {
+ GL4ES3 _gl = gl.getGL4ES3();
+ System.err.println("GL4ES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGL3() ) {
+ GL3 _gl = gl.getGL3();
+ System.err.println("GL3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES3() ) {
+ GLES3 _gl = gl.getGLES3();
+ System.err.println("GLES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES2() ) {
+ GLES2 _gl = gl.getGLES2();
+ System.err.println("GLES2 retrieved, impl. class "+_gl.getClass().getName());
+ }
}
+ @Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
+ @Override
public void display(GLAutoDrawable drawable) {
}
+ @Override
public void dispose(GLAutoDrawable drawable) {
}
});
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
new file mode 100644
index 000000000..43e56c874
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -0,0 +1,542 @@
+/**
+ * Copyright 2012 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 com.jogamp.newt.swt;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+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.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+import javax.media.opengl.GLCapabilities;
+
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.nativewindow.x11.X11Lib;
+import jogamp.newt.Debug;
+import jogamp.newt.swt.SWTEDTUtil;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import com.jogamp.nativewindow.swt.SWTAccessor;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting.
+ * <p>
+ * Implementation allows use of custom {@link GLCapabilities}.
+ * </p>
+ */
+public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
+ private static final boolean DEBUG = Debug.debug("Window");
+
+ private final AbstractGraphicsScreen screen;
+
+ private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private volatile Rectangle clientArea;
+
+ private volatile SWTNativeWindow nativeWindow;
+ private volatile Window newtChild = null;
+ private volatile boolean newtChildReady = false; // ready if SWTEDTUtil is set and newtChild parented
+ private volatile boolean postSetSize = false; // pending resize
+
+ /**
+ * Creates an instance using {@link #NewtCanvasSWT(Composite, int, Window)}
+ * on the SWT thread.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ * @return a new instance
+ */
+ public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) {
+ final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null };
+ parent.getDisplay().syncExec( new Runnable() {
+ @Override
+ public void run() {
+ res[0] = new NewtCanvasSWT( parent, style, child);
+ }
+ });
+ return res[0];
+ }
+
+ /**
+ * Instantiates a NewtCanvas with a NEWT child.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ *
+ * @param parent the SWT composite
+ * @param style additional styles to SWT#NO_BACKGROUND
+ * @param child optional preassigned {@link #Window}, maybe null
+ */
+ public NewtCanvasSWT(final Composite parent, final int style, Window child) {
+ super(parent, style | SWT.NO_BACKGROUND);
+
+ SWTAccessor.setRealized(this, true);
+
+ clientArea = getClientArea();
+
+ final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
+ screen = SWTAccessor.getScreen(device, -1 /* default */);
+ nativeWindow = null;
+
+ if(null != child) {
+ setNEWTChild(child);
+ }
+
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (Event event) {
+ switch (event.type) {
+ case SWT.Paint:
+ if( null != nativeWindow || validateNative() ) {
+ if( newtChildReady ) {
+ if( postSetSize ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ postSetSize = false;
+ }
+ if( SWTAccessor.isOSX ) {
+ newtChild.setPosition(parent.getLocation().x,parent.getLocation().y);
+ }
+ newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ }
+ }
+ break;
+ case SWT.Resize:
+ updateSizeCheck();
+ break;
+ case SWT.Dispose:
+ NewtCanvasSWT.this.dispose();
+ break;
+ }
+ }
+ };
+ addListener (SWT.Resize, listener);
+ addListener (SWT.Paint, listener);
+ addListener (SWT.Dispose, listener);
+ }
+
+ /** assumes nativeWindow == null ! */
+ protected final boolean validateNative() {
+ updateSizeCheck();
+ final Rectangle nClientArea = clientArea;
+ if(0 >= nClientArea.width || 0 >= nClientArea.height) {
+ return false;
+ }
+ screen.getDevice().open();
+
+ /* Native handle for the control, used to associate with GLContext */
+ final long nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+ final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
+ final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
+ }
+ if( visualIDValid ) {
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */
+ final CapabilitiesImmutable caps = new Capabilities();
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps);
+ final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
+ // Thread.dumpStack();
+ }
+ if (null == config) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+
+ nativeWindow = new SWTNativeWindow(config, nativeWindowHandle);
+ reparentWindow( true );
+ }
+
+ return null != nativeWindow;
+ }
+
+ protected final void updateSizeCheck() {
+ final Rectangle oClientArea = clientArea;
+ final Rectangle nClientArea = getClientArea();
+ if ( nClientArea != null &&
+ ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
+ ) {
+ clientArea = nClientArea; // write back new value
+ if(DEBUG) {
+ final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+ System.err.println("NewtCanvasSWT.sizeChanged: ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ }
+ if( newtChildReady ) {
+ newtChild.setSize(clientArea.width, clientArea.height);
+ } else {
+ postSetSize = true;
+ }
+ }
+ }
+
+ @Override
+ public void update() {
+ // don't paint background etc .. nop avoids flickering
+ }
+
+ /**
+ * Destroys this resource:
+ * <ul>
+ * <li> Make the NEWT Child invisible </li>
+ * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
+ * <li> Issues <code>destroy()</code> on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child</li>
+ * </ul>
+ * @see Window#destroy()
+ */
+ @Override
+ public void dispose() {
+ if( null != newtChild ) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.dispose.0: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil()+
+ ",\n\t"+newtChild);
+ }
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hint */);
+ newtChild.destroy();
+ newtChild = null;
+ }
+ screen.getDevice().close();
+ nativeWindow = null;
+ super.dispose();
+ }
+
+ private Rectangle getSWTCanvasPosition() {
+ return super.getBounds();
+ }
+ /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
+ public NativeWindow getNativeWindow() { return nativeWindow; }
+
+ @Override
+ public WindowClosingMode getDefaultCloseOperation() {
+ return newtChildCloseOp; // TODO: implement ?!
+ }
+
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ return newtChildCloseOp = op; // TODO: implement ?!
+ }
+
+
+ boolean isParent() {
+ return null!=newtChild ;
+ }
+
+ boolean isFullscreen() {
+ return null != newtChild && newtChild.isFullscreen();
+ }
+
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(final Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if(null != nativeWindow && null != newChild) {
+ reparentWindow( true );
+ }
+ return prevChild;
+ }
+
+ /** @return the current NEWT child */
+ public Window getNEWTChild() {
+ return newtChild;
+ }
+
+ @Override
+ public boolean setParent(Composite parent) {
+ return super.setParent(parent);
+ }
+
+ /* package */ void configureNewtChild(boolean attach) {
+ newtChildReady = attach;
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ } else {
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ }
+ }
+ }
+
+ void reparentWindow(boolean add) {
+ if( null == newtChild ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(add) {
+ updateSizeCheck();
+ final int w = clientArea.width;
+ final int h = clientArea.height;
+
+ // set SWT EDT and start it
+ {
+ final Display newtDisplay = newtChild.getScreen().getDisplay();
+ final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay());
+ edtUtil.start();
+ newtDisplay.setEDTUtil( edtUtil );
+ }
+
+ newtChild.setSize(w, h);
+ newtChild.reparentWindow(nativeWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ // force this SWT Canvas to be focus-able,
+ // since it is completely covered by the newtChild (z-order).
+ setEnabled(true);
+ } else {
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hints */);
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+ }
+
+ private final void requestFocusNEWTChild() {
+ if( newtChildReady ) {
+ newtChild.setFocusAction(null);
+ newtChild.requestFocus();
+ }
+ }
+
+ @Override
+ public boolean forceFocus() {
+ final boolean res = NewtCanvasSWT.super.forceFocus();
+ requestFocusNEWTChild();
+ return res;
+ }
+
+ private class SWTNativeWindow implements NativeWindow {
+ private final AbstractGraphicsConfiguration config;
+ private final long nativeWindowHandle;
+ private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
+
+ public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) {
+ this.config = config;
+ this.nativeWindowHandle = nativeWindowHandle;
+ if( SWTAccessor.isOSX ) {
+ this.insets = OSXUtil.GetInsets(nativeWindowHandle);
+ } else {
+ this.insets = new Insets(0, 0, 0, 0);
+ }
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ return NativeSurface.LOCK_SUCCESS;
+ }
+
+ @Override
+ public void unlockSurface() { }
+
+ @Override
+ public boolean isSurfaceLockedByOtherThread() {
+ return false;
+ }
+
+ @Override
+ public Thread getSurfaceLockOwner() {
+ return null;
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { }
+
+ @Override
+ public long getSurfaceHandle() {
+ return 0;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
+
+ @Override
+ public AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public long getDisplayHandle() {
+ return config.getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public int getScreenIndex() {
+ return config.getScreen().getIndex();
+ }
+
+ @Override
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) { }
+
+ @Override
+ public void destroy() { }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return nativeWindowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return 0;
+ }
+
+ @Override
+ public int getY() {
+ return 0;
+ }
+
+ @Override
+ public Point getLocationOnScreen(Point point) {
+ final Point los; // client window location on screen
+ if( SWTAccessor.isOSX ) {
+ los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0);
+ // top-level position -> client window position: OSX needs to add SWT parent position incl. insets
+ final Rectangle swtCanvasPosition = getSWTCanvasPosition();
+ los.translate(swtCanvasPosition.x + insets.getLeftWidth(), swtCanvasPosition.y + insets.getTopHeight());
+ } else if (SWTAccessor.isX11) {
+ final AbstractGraphicsScreen s = config.getScreen();
+ los = X11Lib.GetRelativeLocation(s.getDevice().getHandle(), s.getIndex(), nativeWindowHandle, 0 /*root win*/, 0, 0);
+ } else if (SWTAccessor.isWindows) {
+ los = GDIUtil.GetRelativeLocation( nativeWindowHandle, 0 /*root win*/, 0, 0);
+ } else {
+ // fall-back to 0/0
+ los = new Point(0, 0);
+ }
+ if(null!=point) {
+ return point.translate(los);
+ } else {
+ return los;
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return isFocusControl();
+ }
+ };
+
+ static String newtWinHandleToHexString(Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(long l) {
+ return "0x"+Long.toHexString(l);
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 4493e2781..582dc3e1f 100644
--- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -28,6 +28,9 @@
package com.jogamp.newt.util;
+import jogamp.newt.DisplayImpl;
+import com.jogamp.newt.event.NEWTEvent;
+
/**
* EDT stands for Event Dispatch Thread.
* <p>
@@ -60,66 +63,106 @@ public interface EDTUtil {
* @param ms poll period in milliseconds
*/
public void setPollPeriod(long ms);
-
+
/**
- * Create a new EDT. One should invoke <code>reset()</code><br>
- * after <code>invokeStop(..)</code> in case another <code>start()</code> or <code>invoke(..)</code>
- * is expected.
+ * Starts the EDT after it's creation or after {@link #invokeStop(boolean, Runnable) stopping}.
+ * <p>
+ * If the EDT is running, it must be {@link #invokeStop(boolean, Runnable) stopped} first
+ * and the caller should wait {@link #waitUntilStopped() until it's stopped}.
+ * </p>
+ *
+ * @return true if EDT has been successfully restarted, otherwise false
+ * @throws IllegalStateException if EDT is running and not subject to be stopped, i.e. {@link #isRunning()} returns true
*
- * @see #start()
- * @see #invoke(boolean, java.lang.Runnable)
- * @see #invokeStop(java.lang.Runnable)
+ * @see #invokeStop(boolean, java.lang.Runnable)
+ * @see #waitUntilStopped()
*/
- public void reset();
+ public boolean start() throws IllegalStateException;
/**
- * Start the EDT
+ * Returns true if the current thread is the event dispatch thread (EDT).
+ * <p>
+ * The EDT is the platform specific thread dispatching toolkit-events
+ * and executing toolkit-tasks enqueued via {@link #invoke(boolean, Runnable)}.
+ * </p>
+ * <p>
+ * Usually it is the same thread as used to dequeue informal {@link NEWTEvent}s (NEDT), see {@link #isCurrentThreadNEDT()},
+ * however, this may differ, e.g. SWT and AWT implementation.
+ * </p>
*/
- public void start();
+ public boolean isCurrentThreadEDT();
/**
- * @return True if the current thread is the EDT thread
+ * Returns true if the current thread is the internal NEWT event dequeue thread (NEDT).
+ * <p>
+ * The NEDT is the NEWT thread used to dequeue informal {@link NEWTEvent}s enqueued internally
+ * via {@link DisplayImpl#enqueueEvent(boolean, NEWTEvent)}.
+ * </p>
+ * <p>
+ * Usually it is the same thread as the EDT, see {@link #isCurrentThreadEDT()},
+ * however, this may differ, e.g. SWT and AWT implementation.
+ * </p>
*/
- public boolean isCurrentThreadEDT();
+ public boolean isCurrentThreadNEDT();
+
+ /**
+ * Returns <code>true</code> if either {@link #isCurrentThreadEDT()} or {@link #isCurrentThreadNEDT()} is <code>true</code>,
+ * otherwise <code>false</code>.
+ */
+ public boolean isCurrentThreadEDTorNEDT();
/**
- * @return True if EDT is running
+ * @return True if EDT is running and not subject to be stopped.
*/
public boolean isRunning();
- /**
+ /**
* Append the final task to the EDT task queue,
- * signals EDT to stop and wait until stopped.<br>
+ * signals EDT to stop.
+ * <p>
+ * If <code>wait</code> is <code>true</code> methods
+ * blocks until EDT is stopped.
+ * </p>
+ * <p>
+ * <code>task</code> maybe <code>null</code><br/>
* Due to the nature of this method:
* <ul>
* <li>All previous queued tasks will be finished.</li>
* <li>No new tasks are allowed, an Exception is thrown.</li>
* <li>Can be issued from within EDT, ie from within an enqueued task.</li>
- * <li>{@link #reset()} may follow immediately, ie creating a new EDT</li>
+ * <li>{@link #start()} may follow immediately, ie creating a new EDT</li>
* </ul>
+ * </p>
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invokeStop(Runnable finalTask);
+ public boolean invokeStop(boolean wait, Runnable finalTask);
- /**
- * Append task to the EDT task queue.<br>
- * Wait until execution is finished if <code>wait == true</code>.<br>
- * Shall start the thread if not running.<br>
+ /**
+ * Appends task to the EDT task queue if current thread is not EDT,
+ * otherwise execute task immediately.
+ * <p>
+ * Wait until execution is finished if <code>wait == true</code>.
+ * </p>
* Can be issued from within EDT, ie from within an enqueued task.<br>
- *
- * @throws RuntimeException in case EDT is stopped and not {@link #reset()}
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invoke(boolean wait, Runnable task);
+ public boolean invoke(boolean wait, Runnable task);
- /**
+ /**
* Wait until the EDT task queue is empty.<br>
* The last task may still be in execution when this method returns.
+ * @return true if waited for idle, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilIdle();
+ public boolean waitUntilIdle();
/**
* Wait until EDT task is stopped.<br>
- * No <code>stop</code> action is performed, {@link #invokeStop(java.lang.Runnable)} should be used before.
+ * No <code>stop</code> action is performed, {@link #invokeStop(boolean, java.lang.Runnable)} should be used before.
+ * <p>
+ * If caller thread is EDT or NEDT, this call will not block.
+ * </p>
+ * @return true if stopped, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilStopped();
+ public boolean waitUntilStopped();
}
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java
index bbe415b2f..049320b21 100644
--- a/src/newt/classes/com/jogamp/newt/util/MainThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -54,13 +54,13 @@ import jogamp.newt.NEWTJNILibLoader;
* NEWT Utility class MainThread<P>
*
* <p>
- * FIXME: Update this documentation!
+ * FIXME: Update this documentation!
* This class just provides a main-thread utility, forking of a main java class
* on another thread while being able to continue doing platform specific things
* on the main-thread. The latter is essential for eg. MacOSX, where we continue
* to run NSApp.run().
* </p>
- *
+ *
* This class provides a startup singleton <i>main thread</i>,
* from which a new thread with the users main class is launched.<br>
*
@@ -72,17 +72,17 @@ import jogamp.newt.NEWTJNILibLoader;
* use a NEWT multithreaded application with window handling within the different threads,
* even on these restricted platforms.<br>
*
- * To support your NEWT Window platform,
+ * To support your NEWT Window platform,
* you have to pass your <i>main thread</i> actions to {@link #invoke invoke(..)},
- * have a look at the {@link com.jogamp.newt.macosx.MacWindow MacWindow} implementation.<br>
- * <i>TODO</i>: Some hardcoded dependencies exist in this implementation,
+ * have a look at the {@link jogamp.newt.driver.macosx.WindowDriver NEWT Mac OSX Window} driver implementation.<br>
+ * <i>TODO</i>: Some hardcoded dependencies exist in this implementation,
* where you have to patch this code or factor it out. <P>
- *
+ *
* If your platform is not Mac OS X, but you want to test your code without modifying
* this class, you have to set the system property <code>newt.MainThread.force</code> to <code>true</code>.<P>
*
* The code is compatible with all other platform, which support multithreaded windowing handling.
- * Since those platforms won't trigger the <i>main thread</i> serialization, the main method
+ * Since those platforms won't trigger the <i>main thread</i> serialization, the main method
* will be simply executed, in case you haven't set <code>newt.MainThread.force</code> to <code>true</code>.<P>
*
* Test case on Mac OS X (or any other platform):
@@ -92,39 +92,39 @@ import jogamp.newt.NEWTJNILibLoader;
* Which starts 4 threads, each with a window and OpenGL rendering.<br>
*/
public class MainThread {
- private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay";
+ private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.DisplayDriver";
private static final Platform.OSType osType;
private static final boolean isMacOSX;
private static final ThreadGroup rootThreadGroup;
-
+
/** if true, use the main thread EDT, otherwise AWT's EDT */
public static final boolean HINT_USE_MAIN_THREAD;
-
+
static {
- NativeWindowFactory.initSingleton(true);
+ NativeWindowFactory.initSingleton();
NEWTJNILibLoader.loadNEWT();
- HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
+ HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() ||
Debug.getBooleanProperty("newt.MainThread.force", true);
osType = Platform.getOSType();
isMacOSX = osType == Platform.OSType.MACOS;
rootThreadGroup = getRootThreadGroup();
}
-
+
public static boolean useMainThread = false;
-
+
protected static final boolean DEBUG = Debug.debug("MainThread");
private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread
-
+
private static final ThreadGroup getRootThreadGroup() {
ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
ThreadGroup parentGroup;
while ( ( parentGroup = rootGroup.getParent() ) != null ) {
rootGroup = parentGroup;
}
- return rootGroup;
+ return rootGroup;
}
-
+
private static final Thread[] getAllThreads(int[] count) {
int tn;
Thread[] threads = new Thread[ rootThreadGroup.activeCount() ];
@@ -149,17 +149,17 @@ public class MainThread {
t.printStackTrace();
}
}
- return res;
+ return res;
}
private static final int getNonDaemonThreadCount(List<Thread> ignoreThreads) {
int res = 0;
int[] tn = { 0 };
Thread[] threads = getAllThreads(tn);
-
+
for(int i = tn[0] - 1; i >= 0; i--) {
final Thread thread = threads[i];
try {
- if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) {
+ if(thread.isAlive() && !thread.isDaemon() && !ignoreThreads.contains(thread)) {
res++;
if(DEBUG) System.err.println("MainAction.run(): non daemon thread: "+thread);
}
@@ -167,9 +167,9 @@ public class MainThread {
t.printStackTrace();
}
}
- return res;
+ return res;
}
-
+
static class UserApp extends Thread {
private final String mainClassNameShort;
private final String mainClassName;
@@ -181,7 +181,7 @@ public class MainThread {
super();
this.mainClassName=mainClassName;
this.mainClassArgs=mainClassArgs;
-
+
final Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader());
if(null==mainClass) {
throw new ClassNotFoundException("MainAction couldn't find main class "+mainClassName);
@@ -192,7 +192,7 @@ public class MainThread {
setName(getName()+"-UserApp-"+mainClassNameShort);
setDaemon(false);
-
+
if(DEBUG) System.err.println("MainAction(): instantiated: "+getName()+", is daemon "+isDaemon()+", main-class: "+mainClass.getName());
}
@@ -230,32 +230,32 @@ public class MainThread {
if(isMacOSX) {
try {
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0");
+ System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0");
}
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication",
null, null, MainThread.class.getClassLoader());
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X");
+ System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)");
- System.exit(0);
- }
+ System.exit(0);
+ }
}
}
}
private static UserApp mainAction;
- /** Your new java application main entry, which pipelines your application
- * @throws ClassNotFoundException
- * @throws NoSuchMethodException
+ /** Your new java application main entry, which pipelines your application
+ * @throws ClassNotFoundException
+ * @throws NoSuchMethodException
* @throws SecurityException */
public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
final Thread cur = Thread.currentThread();
-
+
useMainThread = HINT_USE_MAIN_THREAD;
if(DEBUG) {
@@ -268,7 +268,7 @@ public class MainThread {
if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) {
throw new RuntimeException("!USE_MAIN_THREAD and no AWT available");
}
-
+
if(args.length==0) {
return;
}
@@ -282,7 +282,7 @@ public class MainThread {
mainAction = new UserApp(mainClassName, mainClassArgs);
if(isMacOSX) {
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton",
null, null, MainThread.class.getClassLoader());
}
@@ -290,24 +290,24 @@ public class MainThread {
try {
cur.setName(cur.getName()+"-MainThread");
} catch (Exception e) {}
-
+
// dispatch user's main thread ..
mainAction.start();
-
+
if(isMacOSX) {
try {
if(DEBUG) {
- System.err.println("MainThread.main(): "+cur.getName()+"- runNSApp");
+ System.err.println("MainThread.main(): "+cur.getName()+"- runNSApp");
}
- ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication",
+ ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication",
null, null, MainThread.class.getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
- }
- if(DEBUG) { System.err.println("MainThread - wait until last non daemon thread ends ..."); }
+ }
+ if(DEBUG) { System.err.println("MainThread - wait until last non daemon thread ends ..."); }
} else {
- // run user's main in this thread
+ // run user's main in this thread
mainAction.run();
}
}
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
deleted file mode 100644
index 8104f207a..000000000
--- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Copyright 2010 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 com.jogamp.newt.util;
-
-import javax.media.nativewindow.util.*;
-
-/** Immutable MonitorMode Class, consisting of it's read only components:<br>
- * <ul>
- * <li>{@link javax.media.nativewindow.util.SurfaceSize} surface memory size</li>
- * <li>{@link javax.media.nativewindow.util.DimensionImmutable} size in [mm]</li>
- * <li><code>refresh rate</code></li>
- * </ul>
- */
-public class MonitorMode {
- SurfaceSize surfaceSize;
- DimensionImmutable screenSizeMM; // in [mm]
- int refreshRate;
-
- public MonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int refreshRate) {
- // Don't validate screenSizeMM and refreshRate, since they may not be supported by the OS
- if(null==surfaceSize) {
- throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
- }
- this.surfaceSize=surfaceSize;
- this.screenSizeMM=screenSizeMM;
- this.refreshRate=refreshRate;
- }
-
- public final SurfaceSize getSurfaceSize() {
- return surfaceSize;
- }
-
- public final DimensionImmutable getScreenSizeMM() {
- return screenSizeMM;
- }
-
- public final int getRefreshRate() {
- return refreshRate;
- }
-
- public final String toString() {
- return new String("[ "+surfaceSize+" x "+refreshRate+" Hz, "+screenSizeMM+" mm ]");
- }
-
- /**
- * Checks whether two size objects are equal. Two instances
- * of <code>MonitorMode</code> are equal if the three components
- * <code>surfaceSize</code> and <code>refreshRate</code>
- * are equal. <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
- * @return <code>true</code> if the two dimensions are equal;
- * otherwise <code>false</code>.
- */
- public final boolean equals(Object obj) {
- if (this == obj) { return true; }
- if (obj instanceof MonitorMode) {
- MonitorMode p = (MonitorMode)obj;
- return getSurfaceSize().equals(p.getSurfaceSize()) &&
- /* getScreenSizeMM().equals(p.getScreenSizeMM()) && */
- getRefreshRate() == p.getRefreshRate() ;
- }
- return false;
- }
-
- /**
- * returns a hash code over <code>surfaceSize</code> and <code>refreshRate</code>.
- * <code>screenSizeMM</code> is kept out intentional to reduce the requirements for finding the current mode.
- */
- public final int hashCode() {
- // 31 * x == (x << 5) - x
- int hash = 31 + getSurfaceSize().hashCode();
- /* hash = ((hash << 5) - hash) + getScreenSizeMM().hashCode(); */
- hash = ((hash << 5) - hash) + getRefreshRate();
- return hash;
- }
-}
-
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
new file mode 100644
index 000000000..fdd7985fe
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
@@ -0,0 +1,258 @@
+/**
+ * Copyright 2010 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 com.jogamp.newt.util;
+
+import com.jogamp.newt.MonitorMode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.SurfaceSize;
+
+/**
+ * Convenient {@link com.jogamp.newt.MonitorMode} utility methods,
+ * filters etc.
+ */
+public class MonitorModeUtil {
+
+ public static int getIndex(List<MonitorMode> monitorModes, MonitorMode search) {
+ return monitorModes.indexOf(search);
+ }
+
+ public static int getIndexByHashCode(List<MonitorMode> monitorModes, MonitorMode search) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ if ( search.hashCode() == monitorModes.get(i).hashCode() ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static MonitorMode getByNativeSizeRateIdAndRotation(List<MonitorMode> monitorModes, MonitorMode.SizeAndRRate sizeAndRate, int modeId, int rotation) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if( mode.getSizeAndRRate().equals(sizeAndRate) && mode.getId() == modeId && mode.getRotation() == rotation ) {
+ return mode;
+ }
+ }
+ }
+ return null;
+ }
+
+ /** Sort the given {@link MonitorMode} collection w/ {@link MonitorMode#compareTo(MonitorMode)} function. */
+ public static void sort(List<MonitorMode> monitorModes, boolean ascendingOrder) {
+ if( ascendingOrder ) {
+ Collections.sort(monitorModes);
+ } else {
+ Collections.sort(monitorModes, MonitorMode.monitorModeComparatorInv);
+ }
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param surfaceSize
+ * @return modes with exact {@link SurfaceSize}. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterBySurfaceSize(List<MonitorMode> monitorModes, SurfaceSize surfaceSize) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getSurfaceSize().equals(surfaceSize)) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param rotation
+ * @return modes with exact rotation. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByRotation(List<MonitorMode> monitorModes, int rotation) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getRotation() == rotation) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param bitsPerPixel
+ * @return modes with exact bpp. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByBpp(List<MonitorMode> monitorModes, int bitsPerPixel) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param flags
+ * @return modes with exact flags. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByFlags(List<MonitorMode> monitorModes, int flags) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if(mode.getFlags() == flags) {
+ out.add(mode);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * @param monitorModes
+ * @param resolution
+ * @return modes with nearest resolution, or matching ones. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByResolution(List<MonitorMode> monitorModes, DimensionImmutable resolution) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ final int resolution_sq = resolution.getHeight()*resolution.getWidth();
+ int mode_dsq=Integer.MAX_VALUE, mode_dsq_idx=0;
+
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final DimensionImmutable res = mode.getSurfaceSize().getResolution();
+ final int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
+ if(dsq<mode_dsq) {
+ mode_dsq = dsq;
+ mode_dsq_idx = i;
+ }
+ if(res.equals(resolution)) {
+ out.add(mode);
+ }
+ }
+ if(out.size() == 0 && 0 <= mode_dsq_idx ) {
+ // nearest ..
+ out.add(monitorModes.get(mode_dsq_idx));
+ }
+ }
+ return out;
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @param refreshRate
+ * @return modes with nearest refreshRate, or matching ones. May return zero sized list for non.
+ */
+ public static List<MonitorMode> filterByRate(List<MonitorMode> monitorModes, float refreshRate) {
+ final List<MonitorMode> out = new ArrayList<MonitorMode>();
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ float mode_dr = Float.MAX_VALUE;
+ int mode_dr_idx = -1;
+ for (int i=0; null!=monitorModes && i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ float dr = Math.abs(refreshRate - mode.getRefreshRate());
+ if(dr<mode_dr) {
+ mode_dr = dr;
+ mode_dr_idx = i;
+ }
+ if(0 == dr) {
+ out.add(mode);
+ }
+ }
+ if(out.size() == 0 && 0 <= mode_dr_idx ) {
+ // nearest ..
+ out.add(monitorModes.get(mode_dr_idx));
+ }
+ }
+ return out;
+ }
+
+ /**
+ * @param monitorModes
+ * @return modes with highest available bpp (color depth). May return zero sized list for non.
+ */
+ public static List<MonitorMode> getHighestAvailableBpp(List<MonitorMode> monitorModes) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ int highest = -1;
+ for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final int bpp = mode.getSurfaceSize().getBitsPerPixel();
+ if (bpp > highest) {
+ highest = bpp;
+ }
+ }
+ return filterByBpp(monitorModes, highest);
+ }
+ return new ArrayList<MonitorMode>();
+ }
+
+ /**
+ *
+ * @param monitorModes
+ * @return modes with highest available refresh rate. May return zero sized list for non.
+ */
+ public static List<MonitorMode> getHighestAvailableRate(List<MonitorMode> monitorModes) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ float highest = -1;
+ for (int i=0; null!=monitorModes && i < monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ final float rate = mode.getRefreshRate();
+ if (rate > highest) {
+ highest = rate;
+ }
+ }
+ return filterByRate(monitorModes, highest);
+ }
+ return new ArrayList<MonitorMode>();
+ }
+
+}
diff --git a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java b/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
deleted file mode 100644
index 93797c5fb..000000000
--- a/src/newt/classes/com/jogamp/newt/util/ScreenModeUtil.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/**
- * Copyright 2010 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 com.jogamp.newt.util;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.newt.ScreenMode;
-import java.util.ArrayList;
-import java.util.List;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.SurfaceSize;
-
-/**
- * Convenient {@link com.jogamp.newt.ScreenMode} utility methods,
- * filters etc.
- */
-public class ScreenModeUtil {
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 2: width and height
- */
- public static final int NUM_RESOLUTION_PROPERTIES = 2;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 1: bpp
- */
- public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 3: ScreenSizeMM[width, height], refresh-rate
- */
- public static final int NUM_MONITOR_MODE_PROPERTIES = 3;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * 1: rotation, native_mode_id
- */
- public static final int NUM_SCREEN_MODE_PROPERTIES = 1;
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation
- * count + all the above
- */
- public static final int NUM_SCREEN_MODE_PROPERTIES_ALL = 8;
-
- public static int getIndex(List<ScreenMode> screenModes, ScreenMode search) {
- return screenModes.indexOf(search);
- }
-
- public static int getIndexByHashCode(List<ScreenMode> screenModes, ScreenMode search) {
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- if ( search.hashCode() == screenModes.get(i).hashCode() ) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * @param screenModes
- * @param resolution
- * @return modes with nearest resolution, or matching ones
- */
- public static List<ScreenMode> filterByResolution(List<ScreenMode> screenModes, DimensionImmutable resolution) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- int resolution_sq = resolution.getHeight()*resolution.getWidth();
- int sm_dsq=resolution_sq, sm_dsq_idx=0;
-
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- DimensionImmutable res = sm.getMonitorMode().getSurfaceSize().getResolution();
- int dsq = Math.abs(resolution_sq - res.getHeight()*res.getWidth());
- if(dsq<sm_dsq) {
- sm_dsq = dsq;
- sm_dsq_idx = i;
- }
- if(res.equals(resolution)) {
- out.add(sm);
- }
- }
- if(out.size()>0) {
- return out;
- }
- // nearest ..
- resolution = screenModes.get(sm_dsq_idx).getMonitorMode().getSurfaceSize().getResolution();
- return filterByResolution(screenModes, resolution);
- }
-
- public static List<ScreenMode> filterBySurfaceSize(List<ScreenMode> screenModes, SurfaceSize surfaceSize) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getMonitorMode().getSurfaceSize().equals(surfaceSize)) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- public static List<ScreenMode> filterByRotation(List<ScreenMode> screenModes, int rotation) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getRotation() == rotation) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- public static List<ScreenMode> filterByBpp(List<ScreenMode> screenModes, int bitsPerPixel) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- if(sm.getMonitorMode().getSurfaceSize().getBitsPerPixel() == bitsPerPixel) {
- out.add(sm);
- }
- }
- return out.size()>0 ? out : null;
- }
-
- /**
- *
- * @param screenModes
- * @param refreshRate
- * @return modes with nearest refreshRate, or matching ones
- */
- public static List<ScreenMode> filterByRate(List<ScreenMode> screenModes, int refreshRate) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int sm_dr = refreshRate;
- int sm_dr_idx = -1;
- List<ScreenMode> out = new ArrayList<ScreenMode>();
- for (int i=0; null!=screenModes && i<screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int dr = Math.abs(refreshRate - sm.getMonitorMode().getRefreshRate());
- if(dr<sm_dr) {
- sm_dr = dr;
- sm_dr_idx = i;
- }
- if(0 == dr) {
- out.add(sm);
- }
- }
- if(out.size()>0) {
- return out;
- }
- refreshRate = screenModes.get(sm_dr_idx).getMonitorMode().getRefreshRate();
- return filterByRate(screenModes, refreshRate);
- }
-
- public static List<ScreenMode> getHighestAvailableBpp(List<ScreenMode> screenModes) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int highest = -1;
- for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int bpp = sm.getMonitorMode().getSurfaceSize().getBitsPerPixel();
- if (bpp > highest) {
- highest = bpp;
- }
- }
- return filterByBpp(screenModes, highest);
- }
-
- public static List<ScreenMode> getHighestAvailableRate(List<ScreenMode> screenModes) {
- if(null==screenModes || screenModes.size()==0) {
- return null;
- }
- int highest = -1;
- for (int i=0; null!=screenModes && i < screenModes.size(); i++) {
- ScreenMode sm = screenModes.get(i);
- int rate = sm.getMonitorMode().getRefreshRate();
- if (rate > highest) {
- highest = rate;
- }
- }
- return filterByRate(screenModes, highest);
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) {
- Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
- return resolution;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) {
- SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
- return surfaceSize;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static MonitorMode streamInMonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int[] monitorProperties, int offset) {
- int refreshRate = monitorProperties[offset++];
- return new MonitorMode(surfaceSize, screenSizeMM, refreshRate);
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static ScreenMode streamInScreenMode(MonitorMode monitorMode, int[] modeProperties, int offset) {
- int rotation = modeProperties[offset++];
- return new ScreenMode(monitorMode, rotation);
- }
-
- /**
- * WARNING: must be synchronized with ScreenMode.h, native implementation
- *
- * @param modeProperties the input data
- * @param offset the offset to the input data
- * @return ScreenMode element matching the input <code>modeProperties</code>,
- * or null if input could not be processed.
- */
- public static ScreenMode streamIn(int[] modeProperties, int offset) {
- return streamInImpl(null, null, null, null, null, modeProperties, offset);
- }
-
- /**
- * WARNING: must be synchronized with ScreenMode.h, native implementation
- *
- * @param resolutionPool hash array of unique resolutions, no duplicates
- * @param surfaceSizePool hash array of unique SurfaceSize, no duplicates
- * @param monitorModePool hash array of unique MonitorMode, no duplicates
- * @param screenModePool hash array of unique ScreenMode, no duplicates
- * @param modeProperties the input data
- * @param offset the offset to the input data
- * @return index of the identical (old or new) ScreenMode element in <code>screenModePool</code>,
- * matching the input <code>modeProperties</code>, or -1 if input could not be processed.
- */
- public static int streamIn(ArrayHashSet<DimensionImmutable> resolutionPool,
- ArrayHashSet<SurfaceSize> surfaceSizePool,
- ArrayHashSet<DimensionImmutable> screenSizeMMPool,
- ArrayHashSet<MonitorMode> monitorModePool,
- ArrayHashSet<ScreenMode> screenModePool,
- int[] modeProperties, int offset) {
- ScreenMode screenMode = streamInImpl(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool,
- modeProperties, offset);
- return screenModePool.indexOf(screenMode);
- }
-
-
- private static ScreenMode streamInImpl(ArrayHashSet<DimensionImmutable> resolutionPool,
- ArrayHashSet<SurfaceSize> surfaceSizePool,
- ArrayHashSet<DimensionImmutable> screenSizeMMPool,
- ArrayHashSet<MonitorMode> monitorModePool,
- ArrayHashSet<ScreenMode> screenModePool,
- int[] modeProperties, int offset) {
- int count = modeProperties[offset];
- if(NUM_SCREEN_MODE_PROPERTIES_ALL != count) {
- throw new RuntimeException("NUM_SCREEN_MODE_PROPERTIES should be "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+count+", len "+(modeProperties.length-offset));
- }
- if(NUM_SCREEN_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
- throw new RuntimeException("properties array too short, should be >= "+NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
- }
- offset++;
- DimensionImmutable resolution = ScreenModeUtil.streamInResolution(modeProperties, offset);
- offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=resolutionPool) {
- resolution = resolutionPool.getOrAdd(resolution);
- }
-
- SurfaceSize surfaceSize = ScreenModeUtil.streamInSurfaceSize(resolution, modeProperties, offset);
- offset += ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES;
- if(null!=surfaceSizePool) {
- surfaceSize = surfaceSizePool.getOrAdd(surfaceSize);
- }
-
- DimensionImmutable screenSizeMM = ScreenModeUtil.streamInResolution(modeProperties, offset);
- offset += ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=screenSizeMMPool) {
- screenSizeMM = screenSizeMMPool.getOrAdd(screenSizeMM);
- }
-
- MonitorMode monitorMode = ScreenModeUtil.streamInMonitorMode(surfaceSize, screenSizeMM, modeProperties, offset);
- offset += ScreenModeUtil.NUM_MONITOR_MODE_PROPERTIES - ScreenModeUtil.NUM_RESOLUTION_PROPERTIES;
- if(null!=monitorModePool) {
- monitorMode = monitorModePool.getOrAdd(monitorMode);
- }
-
- ScreenMode screenMode = ScreenModeUtil.streamInScreenMode(monitorMode, modeProperties, offset);
- if(null!=screenModePool) {
- screenMode = screenModePool.getOrAdd(screenMode);
- }
- return screenMode;
- }
-
- /** WARNING: must be synchronized with ScreenMode.h, native implementation */
- public static int[] streamOut (ScreenMode screenMode) {
- int[] data = new int[NUM_SCREEN_MODE_PROPERTIES_ALL];
- int idx=0;
- data[idx++] = NUM_SCREEN_MODE_PROPERTIES_ALL;
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getWidth();
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getResolution().getHeight();
- data[idx++] = screenMode.getMonitorMode().getSurfaceSize().getBitsPerPixel();
- data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getWidth();
- data[idx++] = screenMode.getMonitorMode().getScreenSizeMM().getHeight();
- data[idx++] = screenMode.getMonitorMode().getRefreshRate();
- data[idx++] = screenMode.getRotation();
- if(NUM_SCREEN_MODE_PROPERTIES_ALL != idx) {
- throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_SCREEN_MODE_PROPERTIES_ALL);
- }
- return data;
- }
-
-}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java
new file mode 100644
index 000000000..8123126ee
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtApplet3Run.java
@@ -0,0 +1,359 @@
+/**
+ * Copyright 2011 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 com.jogamp.newt.util.applet;
+
+import java.util.Locale;
+
+import com.jogamp.plugin.applet.Applet3;
+import com.jogamp.plugin.applet.Applet3Context;
+import com.jogamp.plugin.ui.NativeWindowDownstream;
+import com.jogamp.plugin.ui.NativeWindowUpstream;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSizePos;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+
+/**
+ * Simple GLEventListener deployment as an applet using JOGL. This demo must be
+ * referenced from a web page via an &lt;applet&gt; tag.
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 within the applet area (normal case):
+ * <pre>
+ &lt;applet width=100 height=100&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * Example of an applet tag using GearsES2 in an undecorated, translucent, closeable and always-on-top window:
+ * <pre>
+ &lt;applet width=1 height=1&gt;
+ &lt;param name="java_arguments" value="-Dsun.java2d.noddraw=true"&gt;
+ &lt;param name="gl_event_listener_class" value="com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2"&gt;
+ &lt;param name="gl_profile" value="GL2"&gt;
+ &lt;param name="gl_swap_interval" value="1"&gt;
+ &lt;param name="gl_undecorated" value="true"&gt;
+ &lt;param name="gl_alwaysontop" value="true"&gt;
+ &lt;param name="gl_closeable" value="true"&gt;
+ &lt;param name="gl_alpha" value="1"&gt;
+ &lt;param name="gl_multisamplebuffer" value="0"&gt;
+ &lt;param name="gl_opaque" value="false"&gt;
+ &lt;param name="gl_dx" value="10"&gt;
+ &lt;param name="gl_dy" value="0"&gt;
+ &lt;param name="gl_width" value="100"&gt;
+ &lt;param name="gl_height" value="100"&gt;
+ &lt;param name="gl_nodefaultkeyListener" value="true"&gt;
+ &lt;param name="gl_debug" value="false"&gt;
+ &lt;param name="gl_trace" value="false"&gt;
+ &lt;param name="jnlp_href" value="jogl-newt-applet-runner.jnlp"&gt;
+ &lt;/applet&gt;Hello Gears !
+ * </pre>
+ * </p>
+ */
+public class JOGLNewtApplet3Run implements Applet3 {
+ public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
+
+ GLWindow glWindow = null;
+ JOGLNewtAppletBase base = null;
+ /** if valid glStandalone:=true (own window) ! */
+ int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
+ Applet3Context ctx;
+ boolean glStandalone = false;
+ UpstreamSurfaceHookMutableSizePos upstreamSizePosHook;
+ PointImmutable upstreamLocOnScreen;
+ NativeWindow browserWin;
+
+ final String getParameter(String name) {
+ return ctx.getParameter(name);
+ }
+
+ @Override
+ public NativeWindowDownstream createNativeWindow(final Applet3Context ctx, final NativeWindowUpstream upstreamWin) {
+ this.ctx = ctx;
+
+ String glProfileName=null;
+ boolean glOpaque=true;
+ int glAlphaBits=0;
+ int glNumMultisampleBuffer=0;
+ boolean glUndecorated=false;
+ boolean glAlwaysOnTop=false;
+ try {
+ glProfileName = getParameter("gl_profile");
+ glOpaque = JOGLNewtAppletBase.str2Bool(getParameter("gl_opaque"), glOpaque);
+ glAlphaBits = JOGLNewtAppletBase.str2Int(getParameter("gl_alpha"), glAlphaBits);
+ glNumMultisampleBuffer = JOGLNewtAppletBase.str2Int(getParameter("gl_multisamplebuffer"), glNumMultisampleBuffer);
+ glXd = JOGLNewtAppletBase.str2Int(getParameter("gl_dx"), glXd);
+ glYd = JOGLNewtAppletBase.str2Int(getParameter("gl_dy"), glYd);
+ glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth);
+ glHeight = JOGLNewtAppletBase.str2Int(getParameter("gl_height"), glHeight);
+ glUndecorated = JOGLNewtAppletBase.str2Bool(getParameter("gl_undecorated"), glUndecorated);
+ glAlwaysOnTop = JOGLNewtAppletBase.str2Bool(getParameter("gl_alwaysontop"), glAlwaysOnTop);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+ final GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName));
+ caps.setAlphaBits(glAlphaBits);
+ if(0<glNumMultisampleBuffer) {
+ caps.setSampleBuffers(true);
+ caps.setNumSamples(glNumMultisampleBuffer);
+ }
+ caps.setBackgroundOpaque(glOpaque);
+
+ final AbstractGraphicsDevice aDevice = NativeWindowFactory.createDevice(upstreamWin.getDisplayConnection(),
+ true /* own */); // open and own! (for upstreamLocOnScreen)
+ final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(aDevice, upstreamWin.getScreenIndex());
+ upstreamSizePosHook = new UpstreamSurfaceHookMutableSizePos(upstreamWin.getX(), upstreamWin.getY(),
+ upstreamWin.getWidth(), upstreamWin.getHeight());
+ browserWin = NativeWindowFactory.createWrappedWindow(aScreen, 0 /* surfaceHandle */, upstreamWin.getWindowHandle(),
+ upstreamSizePosHook);
+ upstreamLocOnScreen = NativeWindowFactory.getLocationOnScreen(browserWin);
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet3Run Configuration:");
+ System.err.println("glStandalone: "+glStandalone);
+ System.err.println("glProfileName: "+glProfileName);
+ System.err.println("glOpaque: "+glOpaque);
+ System.err.println("glAlphaBits: "+glAlphaBits);
+ System.err.println("glNumMultisampleBuffer: "+glNumMultisampleBuffer);
+ System.err.println("glUndecorated: "+glUndecorated);
+ System.err.println("glAlwaysOnTop: "+glAlwaysOnTop);
+ System.err.println("UpstreamWin: "+upstreamWin+", LOS "+upstreamLocOnScreen);
+ if(glStandalone) {
+ System.err.println("pos-size: "+glXd+"/"+glYd+" "+glWidth+"x"+glHeight);
+ }
+ }
+
+ final Window w = NewtFactory.createWindow(glStandalone ? null : browserWin, caps);
+ glWindow = GLWindow.create(w);
+ glWindow.setUndecorated(glUndecorated);
+ glWindow.setAlwaysOnTop(glAlwaysOnTop);
+ glWindow.setSize(browserWin.getWidth(), browserWin.getHeight());
+
+ return new NativeWindowDownstream() {
+ @Override
+ public void setVisible(boolean v) {
+ if( null != glWindow ) {
+ glWindow.setVisible(v);
+ }
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ upstreamSizePosHook.setSize(width, height);
+ if( null != glWindow ) {
+ glWindow.setSize(width, height);
+ }
+ }
+
+ @Override
+ public void requestFocus() {
+ if( null != glWindow ) {
+ glWindow.requestFocus();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if( null != glWindow ) {
+ glWindow.destroy();
+ }
+ }
+
+ @Override
+ public NativeWindowUpstream getParent() {
+ return upstreamWin;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ if( null != glWindow ) {
+ return glWindow.getWindowHandle();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != glWindow ) {
+ glWindow.display();
+ }
+ }
+
+ @Override
+ public void notifyPositionChanged(NativeWindowUpstream nw) {
+ upstreamSizePosHook.setPos(nw.getX(), nw.getY());
+ if( null != glWindow ) {
+ glWindow.setPosition(nw.getX(), nw.getY());
+ }
+ }
+ };
+ }
+
+ @Override
+ public void init(Applet3Context ctx) {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.init() START - "+currentThreadName());
+ }
+ this.ctx = ctx;
+ String glEventListenerClazzName=null;
+ int glSwapInterval=0;
+ boolean glDebug=false;
+ boolean glTrace=false;
+ boolean glNoDefaultKeyListener = false;
+ boolean glCloseable=false;
+
+ try {
+ glEventListenerClazzName = getParameter("gl_event_listener_class");
+ glSwapInterval = JOGLNewtAppletBase.str2Int(getParameter("gl_swap_interval"), glSwapInterval);
+ glDebug = JOGLNewtAppletBase.str2Bool(getParameter("gl_debug"), glDebug);
+ glTrace = JOGLNewtAppletBase.str2Bool(getParameter("gl_trace"), glTrace);
+ glNoDefaultKeyListener = JOGLNewtAppletBase.str2Bool(getParameter("gl_nodefaultkeyListener"), glNoDefaultKeyListener);
+ glCloseable = JOGLNewtAppletBase.str2Bool(getParameter("gl_closeable"), glCloseable);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if(null==glEventListenerClazzName) {
+ throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run Configuration:");
+ System.err.println("glEventListenerClazzName: "+glEventListenerClazzName);
+ System.err.println("glSwapInterval: "+glSwapInterval);
+ System.err.println("glDebug: "+glDebug);
+ System.err.println("glTrace: "+glTrace);
+ System.err.println("glNoDefaultKeyListener: "+glNoDefaultKeyListener);
+ System.err.println("glCloseable: "+glCloseable);
+ }
+
+ base = new JOGLNewtAppletBase(glEventListenerClazzName,
+ glSwapInterval,
+ glNoDefaultKeyListener,
+ glCloseable,
+ glDebug,
+ glTrace);
+
+ try {
+ glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
+ glWindow.setDefaultCloseOperation(glCloseable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ base.init(glWindow);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.init() END - "+currentThreadName());
+ }
+ }
+
+ private static String currentThreadName() { return "["+Thread.currentThread().getName()+"]"; }
+
+ @Override
+ public void start() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+glWindow.isVisible()+") - "+currentThreadName());
+ }
+ if( glStandalone ) {
+ glWindow.setSize(glWidth, glHeight);
+ glWindow.setPosition(upstreamLocOnScreen.getX()+glXd, upstreamLocOnScreen.getY()+glYd);
+ glWindow.setVisible(true);
+ glWindow.requestFocus();
+ }
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run start:");
+ System.err.println("GLWindow Pos: "+glWindow.getX()+"/"+glWindow.getY()+" rel, "+glWindow.getLocationOnScreen(null)+" screen");
+ System.err.println("GLWindow: "+glWindow);
+ }
+ base.start();
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.start() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public void stop() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.stop() START - "+currentThreadName());
+ }
+ base.stop();
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.stop() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.destroy() START - "+currentThreadName());
+ }
+ glWindow.setVisible(false); // hide 1st
+ base.destroy(); // destroy glWindow unrecoverable
+ base=null;
+ glWindow=null;
+ browserWin.destroy(); // make sure the open display connection gets closed!
+ browserWin = null;
+ if(DEBUG) {
+ System.err.println("JOGLNewtApplet1Run.destroy() END - "+currentThreadName());
+ }
+ }
+
+ @Override
+ public String getAppletInfo() {
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return null;
+ }
+
+ @Override
+ public String[][] getParameterInfo() {
+ return null;
+ }
+
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
index 082c01c23..bbe6b8527 100755..100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
@@ -25,7 +25,7 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package com.jogamp.newt.awt.applet;
+package com.jogamp.newt.util.applet;
import java.lang.reflect.Field;
import java.security.AccessController;
@@ -33,6 +33,7 @@ import java.security.PrivilegedAction;
import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
@@ -41,6 +42,10 @@ import javax.media.opengl.GLPipelineFactory;
import jogamp.newt.Debug;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
@@ -56,27 +61,28 @@ import com.jogamp.opengl.util.Animator;
public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public static final boolean DEBUG = Debug.debug("Applet");
-
+
String glEventListenerClazzName;
int glSwapInterval;
boolean noDefaultKeyListener;
boolean glClosable;
boolean glDebug;
boolean glTrace;
+ PointerIcon pointerIconTest = null;
GLEventListener glEventListener = null;
GLWindow glWindow = null;
Animator glAnimator=null;
boolean isValid = false;
- NativeWindow awtParent;
+ NativeWindow parentWin;
- public JOGLNewtAppletBase(String glEventListenerClazzName,
+ public JOGLNewtAppletBase(String glEventListenerClazzName,
int glSwapInterval,
boolean noDefaultKeyListener,
boolean glClosable,
boolean glDebug,
boolean glTrace) {
-
+
this.glEventListenerClazzName=glEventListenerClazzName;
this.glSwapInterval=glSwapInterval;
this.noDefaultKeyListener = noDefaultKeyListener;
@@ -111,6 +117,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
try {
final Class<?> clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ @Override
public Class<?> run() {
final ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> clazz = null;
@@ -160,22 +167,6 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public void init(ThreadGroup tg, final GLWindow glWindow) {
isValid = false;
this.glWindow = glWindow;
- this.glWindow.addWindowListener(new WindowAdapter() {
- // Closing action: back to parent!
- @Override
- public void windowDestroyNotify(WindowEvent e) {
- if( WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
- if(null == glWindow.getParent()) {
- // we may be called directly by the native EDT
- new Thread(new Runnable() {
- public void run() {
- glWindow.reparentWindow(awtParent);
- }
- }).start();
- }
- }
- } } );
-
glEventListener = createInstance(glEventListenerClazzName);
if(null == glEventListener) {
return;
@@ -200,7 +191,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
if(glEventListener instanceof KeyListener) {
glWindow.addKeyListener((KeyListener)glEventListener);
}
-
+
if(!noDefaultKeyListener) {
glWindow.addKeyListener(this);
}
@@ -208,26 +199,59 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
// glAnimator = new FPSAnimator(canvas, 60);
- glAnimator = new Animator(tg, glWindow);
+ glAnimator = new Animator();
+ glAnimator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); // No AWT thread involved!
+ glAnimator.setThreadGroup(tg);
+ glAnimator.add(glWindow);
glAnimator.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, null);
-
+
} catch (Throwable t) {
throw new RuntimeException(t);
}
isValid = true;
}
+ private final WindowListener reparentHomeListener = new WindowAdapter() {
+ // Closing action: back to parent!
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ if( isValid() && WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() &&
+ null == glWindow.getParent() && null != parentWin && 0 != parentWin.getWindowHandle() )
+ {
+ // we may be called directly by the native EDT
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if( glWindow.isNativeValid() && null != parentWin && 0 != parentWin.getWindowHandle() ) {
+ glWindow.reparentWindow(parentWin, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ }
+ }
+ }).start();
+ }
+ } };
+
public void start() {
if(isValid) {
glWindow.setVisible(true);
glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
+ if( null == pointerIconTest ) {
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
+ final Display disp = glWindow.getScreen().getDisplay();
+ try {
+ pointerIconTest = disp.createPointerIcon(res, 8, 8);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
glAnimator.start();
- awtParent = glWindow.getParent();
+ parentWin = glWindow.getParent();
+ glWindow.addWindowListener(reparentHomeListener);
}
}
public void stop() {
if(null!=glAnimator) {
+ glWindow.removeWindowListener(reparentHomeListener);
glAnimator.stop();
glWindow.setVisible(false);
}
@@ -250,30 +274,34 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
// ***********************************************************************************
// ***********************************************************************************
+ @Override
public void init(GLAutoDrawable drawable) {
GL _gl = drawable.getGL();
if(glDebug) {
try {
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, _gl, null) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (Exception e) {e.printStackTrace();}
}
if(glTrace) {
try {
// Trace ..
_gl = _gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, _gl, new Object[] { System.err } ) );
- } catch (Exception e) {e.printStackTrace();}
+ } catch (Exception e) {e.printStackTrace();}
}
if(glSwapInterval>=0) {
_gl.setSwapInterval(glSwapInterval);
}
}
+ @Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
+ @Override
public void display(GLAutoDrawable drawable) {
}
+ @Override
public void dispose(GLAutoDrawable drawable) {
}
@@ -281,27 +309,82 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
// ***********************************************************************************
// ***********************************************************************************
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
- }
- public void keyTyped(KeyEvent e) {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='d') {
- glWindow.setUndecorated(!glWindow.isUndecorated());
+ new Thread() {
+ public void run() {
+ glWindow.setUndecorated(!glWindow.isUndecorated());
+ } }.start();
} if(e.getKeyChar()=='f') {
- glWindow.setFullscreen(!glWindow.isFullscreen());
+ new Thread() {
+ public void run() {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ } }.start();
} else if(e.getKeyChar()=='a') {
- glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
- } else if(e.getKeyChar()=='r' && null!=awtParent) {
- if(null == glWindow.getParent()) {
- glWindow.reparentWindow(awtParent);
- } else {
- glWindow.reparentWindow(null);
- if(glClosable) {
- glWindow.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
- }
- }
+ new Thread() {
+ public void run() {
+ glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
+ } }.start();
+ } else if(e.getKeyChar()=='r' && null!=parentWin) {
+ new Thread() {
+ public void run() {
+ if(null == glWindow.getParent()) {
+ glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */);
+ } else {
+ final InsetsImmutable insets = glWindow.getInsets();
+ final int x, y;
+ if ( 0 >= insets.getTopHeight() ) {
+ // fail safe ..
+ x = 32;
+ y = 32;
+ } else {
+ x = insets.getLeftWidth();
+ y = insets.getTopHeight();
+ }
+ glWindow.reparentWindow(null, x, y, 0 /* hints */);
+ glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE );
+ }
+ } }.start();
+ } else if(e.getKeyChar()=='c') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set pointer-icon pre]");
+ final PointerIcon currentPI = glWindow.getPointerIcon();
+ glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest);
+ System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
+ } }.start();
+ } else if(e.getKeyChar()=='i') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
+ glWindow.setPointerVisible(!glWindow.isPointerVisible());
+ System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
+ } }.start();
+ } else if(e.getKeyChar()=='j') {
+ new Thread() {
+ public void run() {
+ final Thread t = glWindow.setExclusiveContextThread(null);
+ System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
+ glWindow.confinePointer(!glWindow.isPointerConfined());
+ System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
+ glWindow.setExclusiveContextThread(t);
+ } }.start();
+ } else if(e.getKeyChar()=='w') {
+ new Thread() {
+ public void run() {
+ System.err.println("[set mouse pos pre]");
+ glWindow.warpPointer(glWindow.getWidth()/2, glWindow.getHeight()/2);
+ System.err.println("[set mouse pos post]");
+ } }.start();
}
}
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java b/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java
new file mode 100644
index 000000000..db0e8fc45
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/util/applet/VersionApplet3.java
@@ -0,0 +1,226 @@
+package com.jogamp.newt.util.applet;
+
+import com.jogamp.plugin.applet.Applet3;
+import com.jogamp.plugin.applet.Applet3Context;
+import com.jogamp.plugin.ui.NativeWindowDownstream;
+import com.jogamp.plugin.ui.NativeWindowUpstream;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.JoglVersion;
+
+public class VersionApplet3 implements Applet3 {
+
+ public static void main(String[] args) {
+ VersionApplet3 va = new VersionApplet3();
+
+ final NativeWindowDownstream nwc = va.createNativeWindow(null, new NativeWindowUpstream() {
+ @Override
+ public long getWindowHandle() {
+ return 0;
+ }
+ @Override
+ public int getWidth() {
+ return 64;
+ }
+ @Override
+ public int getHeight() {
+ return 64;
+ }
+ @Override
+ public String getDisplayConnection() {
+ return null; // default
+ }
+ @Override
+ public int getScreenIndex() {
+ return 0; // default
+ }
+ @Override
+ public void notifySurfaceUpdated(NativeWindowDownstream swappedWin) {
+ // NOP
+ }
+ @Override
+ public int getX() {
+ return 0;
+ }
+ @Override
+ public int getY() {
+ return 0;
+ }
+ });
+ va.init(null);
+ va.start();
+ va.stop();
+ va.destroy();
+ nwc.destroy();
+ }
+
+ GLWindow canvas;
+
+ @Override
+ public NativeWindowDownstream createNativeWindow(final Applet3Context ctx, final NativeWindowUpstream parentWin) {
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ final Window w = NewtFactory.createWindow(parentWin.getDisplayConnection(), parentWin.getScreenIndex(), parentWin.getWindowHandle(), caps);
+ canvas = GLWindow.create(w);
+ canvas.setSize(parentWin.getWidth(), parentWin.getHeight());
+
+ return new NativeWindowDownstream() {
+ @Override
+ public void setVisible(boolean v) {
+ if( null != canvas ) {
+ canvas.setVisible(v);
+ }
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ if( null != canvas ) {
+ canvas.setSize(width, height);
+ }
+ }
+
+ @Override
+ public void requestFocus() {
+ if( null != canvas ) {
+ canvas.requestFocus();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ if( null != canvas ) {
+ canvas.destroy();
+ }
+ }
+
+ @Override
+ public NativeWindowUpstream getParent() {
+ return parentWin;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ if( null != canvas ) {
+ return canvas.getWindowHandle();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void display() {
+ if( null != canvas ) {
+ canvas.display();
+ }
+ }
+
+ @Override
+ public void notifyPositionChanged(NativeWindowUpstream nw) {
+ if( null != canvas ) {
+ canvas.setPosition(nw.getX(), nw.getY());
+ }
+ }
+ };
+ }
+
+ @Override
+ public void init(Applet3Context ctx) {
+ System.err.println("VersionApplet: init() - begin");
+ canvas.addGLEventListener(new GLInfo());
+ System.err.println("VersionApplet: init() - end");
+ }
+
+ @Override
+ public void start() {
+ System.err.println("VersionApplet: start() - begin");
+
+ String s;
+
+ s = VersionUtil.getPlatformInfo().toString();
+ System.err.println(s);
+
+ s = GlueGenVersion.getInstance().toString();
+ System.err.println(s);
+
+ /*
+ s = NativeWindowVersion.getInstance().toString();
+ System.err.println(s);
+ */
+
+ s = JoglVersion.getInstance().toString();
+ System.err.println(s);
+
+ GLDrawableFactory factory = GLDrawableFactory.getFactory(canvas.getGLProfile());
+ List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(null);
+ for(int i=0; i<availCaps.size(); i++) {
+ s = availCaps.get(i).toString();
+ System.err.println(s);
+ }
+ canvas.display();
+ System.err.println("VersionApplet: start() - end");
+ }
+
+ @Override
+ public void stop() {
+ System.err.println("VersionApplet: stop() - begin");
+ canvas.setVisible(false);
+ System.err.println("VersionApplet: stop() - end");
+ }
+
+ @Override
+ public void destroy() {
+ System.err.println("VersionApplet: destroy() - start");
+ if(null!=canvas) {
+ canvas.destroy();
+ canvas = null;
+ }
+ System.err.println("VersionApplet: destroy() - end");
+ }
+
+ @Override
+ public String getAppletInfo() {
+ return null;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return null;
+ }
+
+ @Override
+ public String[][] getParameterInfo() {
+ return null;
+ }
+
+ class GLInfo implements GLEventListener {
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ GL gl = drawable.getGL();
+ String s = JoglVersion.getGLInfo(gl, null).toString();
+ System.err.println(s);
+ }
+ @Override
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ }
+ @Override
+ public void display(GLAutoDrawable drawable) {
+ }
+ @Override
+ public void dispose(GLAutoDrawable drawable) {
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/Debug.java b/src/newt/classes/jogamp/newt/Debug.java
index 3c83da4d9..7ef2d7ffc 100644
--- a/src/newt/classes/jogamp/newt/Debug.java
+++ b/src/newt/classes/jogamp/newt/Debug.java
@@ -1,21 +1,22 @@
/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,17 +29,20 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
package jogamp.newt;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,9 +51,15 @@ public class Debug extends PropertyAccess {
// Some common properties
private static final boolean verbose;
private static final boolean debugAll;
-
+
static {
- PropertyAccess.addTrustedPrefix("newt.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("newt.");
+ return null;
+ } } );
+
verbose = isPropertyDefined("newt.verbose", true);
debugAll = isPropertyDefined("newt.debug", true);
if (verbose) {
@@ -60,27 +70,18 @@ public class Debug extends PropertyAccess {
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static final int getIntProperty(final String property, final boolean jnlpAlias, int defaultValue) {
- return PropertyAccess.getIntProperty(property, jnlpAlias, null, defaultValue);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(String subcomponent) {
return debugAll() || isPropertyDefined("newt.debug." + subcomponent, true);
}
}
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
index fd757fba6..d481ce8f9 100644
--- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
@@ -38,6 +38,7 @@
package jogamp.newt;
import java.util.ArrayList;
+
import javax.media.nativewindow.NativeWindowException;
import jogamp.common.util.locks.LockDebugUtil;
@@ -49,127 +50,183 @@ import com.jogamp.newt.util.EDTUtil;
public class DefaultEDTUtil implements EDTUtil {
public static final boolean DEBUG = Debug.debug("EDT");
- private ThreadGroup threadGroup;
- private EventDispatchThread edt = null;
- private Object edtLock = new Object(); // locking the EDT start/stop state
- private String name;
- int start_iter=0;
- private Runnable dispatchMessages;
+ /** Used to implement {@link #invokeStop(boolean, Runnable)}. */
+ private static final Object TASK_ATTACHMENT_STOP = new Object();
+ /** Used to provoke an exception on the EDT while waiting / blocking. Merely exists to test code.*/
+ private static final Object TASK_ATTACHMENT_TEST_ERROR = new Object();
+
+ private final Object edtLock = new Object(); // locking the EDT start/stop state
+ private /* final */ ThreadGroup threadGroup;
+ private final String name;
+ private final Runnable dispatchMessages;
+ private NEDT edt = null;
+ private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
public DefaultEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) {
this.threadGroup = tg;
this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
this.dispatchMessages=dispatchMessages;
- this.edt = new EventDispatchThread(threadGroup, name);
+ this.edt = new NEDT(threadGroup, name);
this.edt.setDaemon(true); // don't stop JVM from shutdown ..
}
+ @Override
final public long getPollPeriod() {
return pollPeriod;
}
+ @Override
final public void setPollPeriod(long ms) {
pollPeriod = ms;
}
-
- public final void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+
+ @Override
+ public final boolean start() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( edt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", EDT "+edt.getName()+", isRunning "+edt.isRunning+", shouldStop "+edt.shouldStop);
+ }
if(DEBUG) {
if(edt.tasks.size()>0) {
- System.err.println(Thread.currentThread()+": EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
- // Thread.dumpStack();
+ System.err.println(Thread.currentThread()+": Default-EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
+ }
+ System.err.println(Thread.currentThread()+": Default-EDT reset - edt: "+edt);
+ }
+ if( edt.getState() != Thread.State.NEW ) {
+ if( null != threadGroup && threadGroup.isDestroyed() ) {
+ // best thing we can do is to use this thread's TG
+ threadGroup = Thread.currentThread().getThreadGroup();
}
- System.err.println(Thread.currentThread()+": EDT reset - edt: "+edt);
+ edt = new NEDT(threadGroup, name);
+ edt.setDaemon(true); // don't stop JVM from shutdown ..
}
- this.edt = new EventDispatchThread(threadGroup, name);
- this.edt.setDaemon(true); // don't stop JVM from shutdown ..
+ startImpl();
}
+ return invoke(true, nullTask);
}
- public final void start() {
- synchronized(edtLock) {
- if(!edt.isRunning() && !edt.shouldStop) {
- if(edt.isAlive()) {
- throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
- }
- start_iter++;
- edt.setName(name+start_iter);
- edt.shouldStop = false;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT START - edt: "+edt);
- // Thread.dumpStack();
- }
- edt.start();
- }
+ private final void startImpl() {
+ if(edt.isAlive()) {
+ throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning+", shouldStop "+edt.shouldStop+", edt: "+edt+", tasks: "+edt.tasks.size());
}
+ start_iter++;
+ edt.setName(name+start_iter);
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Default-EDT START - edt: "+edt);
+ }
+ edt.start();
}
+ @Override
public final boolean isCurrentThreadEDT() {
- return edt == Thread.currentThread();
+ return edt == Thread.currentThread(); // EDT == NEDT
+ }
+
+ @Override
+ public final boolean isCurrentThreadNEDT() {
+ return edt == Thread.currentThread(); // EDT == NEDT
}
+ @Override
+ public final boolean isCurrentThreadEDTorNEDT() {
+ return edt == Thread.currentThread(); // EDT == NEDT
+ }
+
+ @Override
public final boolean isRunning() {
return edt.isRunning() ;
}
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ @Override
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Default-EDT.invokeStop wait "+wait);
+ Thread.dumpStack();
+ }
+ return invokeImpl(wait, task, true /* stop */, false /* provokeError */);
}
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invokeAndWaitError(Runnable task) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Default-EDT.invokeAndWaitError");
+ Thread.dumpStack();
+ }
+ return invokeImpl(true /* wait */, task, false /* stop */, true /* provokeError */);
}
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
- if(task == null) {
- throw new RuntimeException("Null Runnable");
- }
+ @Override
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false /* stop */, false /* provokeError */);
+ }
+
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop, boolean provokeError) {
Throwable throwable = null;
RunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
synchronized(rTaskLock) { // lock the optional task execution
synchronized(edtLock) { // lock the EDT status
if( edt.shouldStop ) {
// drop task ..
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt);
if(DEBUG) {
- System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+edt);
Thread.dumpStack();
}
- return;
- }
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- edt.shouldStop = true;
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - tasks: "+edt.tasks.size()+" - "+edt);
- // Thread.dumpStack();
- }
+ return false;
}
if( isCurrentThreadEDT() ) {
- task.run();
+ if(null != task) {
+ task.run();
+ }
wait = false; // running in same thread (EDT) -> no wait
- if(stop && edt.tasks.size()>0) {
- System.err.println("Warning: EDT about (2) to stop, having remaining tasks: "+edt.tasks.size()+" - "+edt);
- if(DEBUG) {
- Thread.dumpStack();
+ if( stop ) {
+ edt.shouldStop = true;
+ if( edt.tasks.size()>0 ) {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT about (2) to stop, task executed. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
}
} else {
- synchronized(edt.tasks) {
- start(); // start if not started yet and !shouldStop
- wait = wait && edt.isRunning();
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */);
- if(stop) {
- rTask.setAttachment(new Boolean(true)); // mark final task
+ if( !edt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is not running, dropping task. NEDT "+edt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
}
- // append task ..
- edt.tasks.add(rTask);
- edt.tasks.notifyAll();
+ return false;
+ } else if( stop && null == task ) {
+ task = nullTask; // ensures execution triggering stop
+ }
+
+ if(null != task) {
+ synchronized(edt.tasks) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ if(stop) {
+ rTask.setAttachment(TASK_ATTACHMENT_STOP); // mark final task, will imply shouldStop:=true
+ } else if(provokeError) {
+ rTask.setAttachment(TASK_ATTACHMENT_TEST_ERROR);
+ }
+ // append task ..
+ edt.tasks.add(rTask);
+ edt.tasks.notifyAll();
+ }
+ } else {
+ wait = false;
}
}
}
@@ -189,22 +246,26 @@ public class DefaultEDTUtil implements EDTUtil {
throw new RuntimeException(throwable);
}
}
- }
- if(DEBUG && stop) {
- System.err.println(Thread.currentThread()+": EDT signal STOP X edt: "+edt);
+ if(DEBUG) {
+ if( stop) {
+ System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt);
+ }
+ }
+ return true;
}
}
- final public void waitUntilIdle() {
- final EventDispatchThread _edt;
+ @Override
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
synchronized(edtLock) {
_edt = edt;
}
- if(!_edt.isRunning() || _edt == Thread.currentThread()) {
- return;
+ if(!_edt.isRunning || _edt == Thread.currentThread()) {
+ return false;
}
synchronized(_edt.tasks) {
- while(_edt.isRunning() && _edt.tasks.size()>0) {
+ while(_edt.isRunning && _edt.tasks.size()>0) {
try {
_edt.tasks.notifyAll();
_edt.tasks.wait();
@@ -212,34 +273,39 @@ public class DefaultEDTUtil implements EDTUtil {
e.printStackTrace();
}
}
+ return true;
}
}
- final public void waitUntilStopped() {
+ @Override
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- if(edt.isRunning() && edt != Thread.currentThread() ) {
- while(edt.isRunning()) {
+ if(edt.isRunning && edt != Thread.currentThread() ) {
+ while( edt.isRunning ) {
try {
edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
- class EventDispatchThread extends Thread {
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
- ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks
+ final ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks
- public EventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(ThreadGroup tg, String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -249,24 +315,24 @@ public class DefaultEDTUtil implements EDTUtil {
}
private final void validateNoRecursiveLocksHold() {
- if(Lock.DEBUG) {
- if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
- LockDebugUtil.dumpRecursiveLockTrace(System.err);
- throw new InternalError("XXX");
- }
+ if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
+ LockDebugUtil.dumpRecursiveLockTrace(System.err);
+ throw new InternalError("XXX");
}
}
-
- /**
+
+ /**
* Utilizing locking only on tasks and its execution,
* not for event dispatching.
*/
@Override
final public void run() {
if(DEBUG) {
- System.err.println(getName()+": EDT run() START "+ getName());
+ System.err.println(getName()+": Default-EDT run() START "+ getName());
+ }
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
}
- validateNoRecursiveLocksHold();
RuntimeException error = null;
try {
do {
@@ -289,13 +355,24 @@ public class DefaultEDTUtil implements EDTUtil {
if(tasks.size()>0) {
task = tasks.remove(0);
tasks.notifyAll();
+ final Object attachment = task.getAttachment();
+ if( TASK_ATTACHMENT_STOP == attachment ) {
+ shouldStop = true;
+ } else if( TASK_ATTACHMENT_TEST_ERROR == attachment ) {
+ tasks.add(0, task);
+ task = null;
+ throw new RuntimeException("TASK_ATTACHMENT_TEST_ERROR");
+ }
}
}
if(null!=task) {
task.run();
- validateNoRecursiveLocksHold();
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
+ }
if(!task.hasWaiter() && null != task.getThrowable()) {
// at least dump stack-trace in case nobody waits for result
+ System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString());
task.getThrowable().printStackTrace();
}
}
@@ -306,41 +383,30 @@ public class DefaultEDTUtil implements EDTUtil {
if(t instanceof RuntimeException) {
error = (RuntimeException) t;
} else {
- error = new RuntimeException("Within EDT", t);
+ error = new RuntimeException("Within Default-EDT", t);
}
} finally {
+ final String msg = getName()+": Default-EDT finished w/ "+tasks.size()+" left";
if(DEBUG) {
- RunnableTask rt = ( tasks.size() > 0 ) ? tasks.get(0) : null ;
- System.err.println(getName()+": EDT run() END "+ getName()+", tasks: "+tasks.size()+", "+rt+", "+error);
+ System.err.println(msg+", "+error);
}
synchronized(edtLock) {
- if(null==error) {
- synchronized(tasks) {
- // drain remaining tasks (stop not on EDT),
- // while having tasks and no previous-task, or previous-task is non final
- RunnableTask task = null;
- while ( ( null == task || task.getAttachment() == null ) && tasks.size() > 0 ) {
- task = tasks.remove(0);
- task.run();
- tasks.notifyAll();
- }
- if(DEBUG) {
- if(null!=task && task.getAttachment()==null) {
- System.err.println(getName()+" Warning: EDT exit: Last task Not Final: "+tasks.size()+", "+task+" - "+edt);
- } else if(tasks.size()>0) {
- System.err.println(getName()+" Warning: EDT exit: Remaining tasks Post Final: "+tasks.size());
- }
- Thread.dumpStack();
- }
+ int i = 0;
+ while( tasks.size() > 0 ) {
+ // notify all waiter
+ final String msg2 = msg+", task #"+i;
+ final Throwable t = null != error ? new Throwable(msg2, error) : new Throwable(msg2);
+ final RunnableTask rt = tasks.remove(0);
+ if( null != rt ) {
+ rt.flush(t);
+ i++;
}
}
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
+ isRunning = false;
+ edtLock.notifyAll();
}
if(DEBUG) {
- System.err.println(getName()+": EDT run() EXIT "+ getName()+", "+error);
+ System.err.println(msg+" EXIT, exception: "+error);
}
if(null!=error) {
throw error;
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index a0bbcc264..952e611f2 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,49 +29,236 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
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 com.jogamp.opengl.util.PNGPixelRect;
+
+import java.io.IOException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
+ private static final boolean pngUtilAvail;
+
+ static {
+ NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
+ @Override
+ public void run() {
+ WindowImpl.shutdownAll();
+ ScreenImpl.shutdownAll();
+ DisplayImpl.shutdownAll();
+ }
+ });
+
+ final ClassLoader cl = DisplayImpl.class.getClassLoader();
+ pngUtilAvail = ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
+ }
+
+ public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
+
+ final ArrayList<PointerIconImpl> pointerIconList = new ArrayList<PointerIconImpl>();
+
+ /** Executed from EDT! */
+ private void destroyAllPointerIconFromList(final long dpy) {
+ synchronized(pointerIconList) {
+ final int count = pointerIconList.size();
+ for( int i=0; i < count; i++ ) {
+ final PointerIconImpl item = pointerIconList.get(i);
+ if(DEBUG) {
+ System.err.println("destroyAllPointerIconFromList: dpy "+toHexString(dpy)+", # "+i+"/"+count+": "+item+" @ "+getThreadName());
+ }
+ if( null != item && item.isValid() ) {
+ item.destroyOnEDT(dpy);
+ }
+ }
+ pointerIconList.clear();
+ }
+ }
+
+ @Override
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+ @Override
+ public boolean getNativePointerIconForceDirectNIO() { return false; }
- private static Class<?> getDisplayClass(String type)
- throws ClassNotFoundException
+ @Override
+ public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException
{
- Class<?> displayClass = NewtFactory.getCustomClass(type, "Display");
- if(null==displayClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- displayClass = Class.forName("jogamp.newt.driver.android.AndroidDisplay");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- displayClass = Class.forName("jogamp.newt.driver.kd.KDDisplay");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- displayClass = Class.forName("jogamp.newt.driver.windows.WindowsDisplay");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- displayClass = Class.forName("jogamp.newt.driver.macosx.MacDisplay");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- displayClass = Class.forName("jogamp.newt.driver.x11.X11Display");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- displayClass = Class.forName("jogamp.newt.driver.awt.AWTDisplay");
- } else {
- throw new RuntimeException("Unknown display type \"" + type + "\"");
+ if( null == pngResource || 0 >= pngResource.resourceCount() ) {
+ throw new IllegalArgumentException("Null or invalid pngResource "+pngResource);
+ }
+ if( !pngUtilAvail ) {
+ return null;
+ }
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValidAsync() ) {
+ throw new IllegalStateException("Display.createPointerIcon: Display invalid "+DisplayImpl.this);
+ }
+ final URLConnection urlConn = pngResource.resolve(0);
+ if( null == urlConn ) {
+ throw new IOException("Could not resolve "+pngResource.resourcePaths[0]);
+ }
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(),
+ getNativePointerIconPixelFormat(),
+ getNativePointerIconForceDirectNIO(),
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ final long handle = createPointerIconImplChecked(image.getPixelformat(), image.getSize().getWidth(), image.getSize().getHeight(),
+ image.getPixels(), hotX, hotY);
+ final PointImmutable hotspot = new Point(hotX, hotY);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot);
+ }
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+res[0]);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
+ }
+
+ @Override
+ public final PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException
+ {
+ if( null == pixelrect ) {
+ throw new IllegalArgumentException("Null or pixelrect");
+ }
+ final PixelRectangle fpixelrect;
+ if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) {
+ // conversion !
+ fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(),
+ 0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() );
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect);
+ }
+ } else if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixelrect.getPixels()) ) {
+ // transfer to direct NIO
+ final ByteBuffer sBB = pixelrect.getPixels();
+ final ByteBuffer dBB = Buffers.newDirectByteBuffer(sBB.array(), sBB.arrayOffset());
+ fpixelrect = new PixelRectangle.GenericPixelRect(pixelrect.getPixelformat(), pixelrect.getSize(), pixelrect.getStride(), pixelrect.isGLOriented(), dBB);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-NIO "+pixelrect+" -> "+fpixelrect);
+ }
+ } else {
+ fpixelrect = pixelrect;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: No conversion "+fpixelrect);
}
}
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValidAsync() ) {
+ throw new IllegalStateException("Display.createPointerIcon: Display invalid "+DisplayImpl.this);
+ }
+ if( null != fpixelrect ) {
+ final long handle = createPointerIconImplChecked(fpixelrect.getPixelformat(),
+ fpixelrect.getSize().getWidth(),
+ fpixelrect.getSize().getHeight(),
+ fpixelrect.getPixels(), hotX, hotY);
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, fpixelrect, new Point(hotX, hotY), handle);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected final long createPointerIconImplChecked(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ if( getNativePointerIconPixelFormat() != pixelformat ) {
+ throw new IllegalArgumentException("Pixelformat no "+getNativePointerIconPixelFormat()+", but "+pixelformat);
+ }
+ if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("pixel buffer is not direct "+pixels);
+ }
+ return createPointerIconImpl(pixelformat, width, height, pixels, hotX, hotY);
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return 0;
+ }
+
+ /** Executed from EDT! */
+ protected void destroyPointerIconImpl(final long displayHandle, long piHandle) { }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
+ private static Class<?> getDisplayClass(String type)
+ throws ClassNotFoundException
+ {
+ final Class<?> displayClass = NewtFactory.getCustomClass(type, "DisplayDriver");
if(null==displayClass) {
- throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".Display>");
+ throw new ClassNotFoundException("Failed to find NEWT Display Class <"+type+".DisplayDriver>");
}
return displayClass;
}
@@ -79,12 +266,12 @@ public abstract class DisplayImpl extends Display {
/** Make sure to reuse a Display with the same name */
public static Display create(String type, String name, final long handle, boolean reuse) {
try {
- Class<?> displayClass = getDisplayClass(type);
- DisplayImpl display = (DisplayImpl) displayClass.newInstance();
+ final Class<?> displayClass = getDisplayClass(type);
+ final DisplayImpl display = (DisplayImpl) displayClass.newInstance();
name = display.validateDisplayName(name, handle);
synchronized(displayList) {
if(reuse) {
- Display display0 = Display.getLastDisplayOf(type, name, -1);
+ final Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
if(null != display0) {
if(DEBUG) {
System.err.println("Display.create() REUSE: "+display0+" "+getThreadName());
@@ -92,16 +279,17 @@ public abstract class DisplayImpl extends Display {
return display0;
}
}
+ display.exclusive = !reuse;
display.name = name;
display.type=type;
- display.destroyWhenUnused=false;
display.refCount=0;
display.id = serialno++;
display.fqname = getFQName(display.type, display.name, display.id);
display.hashCode = display.fqname.hashCode();
- displayList.add(display);
+ display.setEDTUtil( display.edtUtil ); // device's default if EDT is used, or null
+ Display.addDisplay2List(display);
}
- display.createEDTUtil();
+
if(DEBUG) {
System.err.println("Display.create() NEW: "+display+" "+getThreadName());
}
@@ -132,118 +320,211 @@ public abstract class DisplayImpl extends Display {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
- public synchronized final void createNative()
+ @Override
+ public synchronized final void createNative()
throws NativeWindowException
{
- if(null==aDevice) {
+ if( null == aDevice ) {
if(DEBUG) {
System.err.println("Display.createNative() START ("+getThreadName()+", "+this+")");
}
final DisplayImpl f_dpy = this;
try {
runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
f_dpy.createNativeImpl();
}});
} catch (Throwable t) {
throw new NativeWindowException(t);
}
- if(null==aDevice) {
+ if( null == aDevice ) {
throw new NativeWindowException("Display.createNative() failed to instanciate an AbstractGraphicsDevice");
}
- if(DEBUG) {
- System.err.println("Display.createNative() END ("+getThreadName()+", "+this+")");
- }
synchronized(displayList) {
displaysActive++;
+ if(DEBUG) {
+ System.err.println("Display.createNative() END ("+getThreadName()+", "+this+", active "+displaysActive+")");
+ }
}
}
}
- protected boolean shallRunOnEDT() {
- return true;
- }
-
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
+ def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
- System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("Display.createEDTUtil("+getFQName()+"): "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
+ @Override
+ public synchronized EDTUtil setEDTUtil(final EDTUtil usrEDTUtil) {
+ final EDTUtil oldEDTUtil = edtUtil;
+ if( null != usrEDTUtil && usrEDTUtil == oldEDTUtil ) {
+ if( DEBUG ) {
+ System.err.println("Display.setEDTUtil: "+usrEDTUtil+" - keep!");
+ }
+ return oldEDTUtil;
+ }
+ if(DEBUG) {
+ final String msg = ( null == usrEDTUtil ) ? "default" : "custom";
+ System.err.println("Display.setEDTUtil("+msg+"): "+oldEDTUtil+" -> "+usrEDTUtil);
+ }
+ stopEDT( oldEDTUtil, null );
+ edtUtil = ( null == usrEDTUtil ) ? createEDTUtil() : usrEDTUtil;
+ return oldEDTUtil;
+ }
+
+ @Override
public final EDTUtil getEDTUtil() {
return edtUtil;
}
- private void stopEDT(final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil ) {
- edtUtil.invokeStop(task);
- } else {
+ private static void stopEDT(final EDTUtil edtUtil, final Runnable task) {
+ if( null != edtUtil ) {
+ if( edtUtil.isRunning() ) {
+ final boolean res = edtUtil.invokeStop(true, task);
+ if( DEBUG ) {
+ if ( !res ) {
+ System.err.println("Warning: invokeStop() failed");
+ Thread.dumpStack();
+ }
+ }
+ }
+ edtUtil.waitUntilStopped();
+ // ready for restart ..
+ } else if( null != task ) {
task.run();
}
}
public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if( shallRunOnEDT() && null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
- edtUtil.invoke(wait, task);
- } else {
- task.run();
+ final EDTUtil _edtUtil = edtUtil;
+ if( !_edtUtil.isRunning() ) { // start EDT if not running yet
+ synchronized( this ) {
+ if( !_edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ if( DEBUG ) {
+ System.err.println("Info: EDT start "+Thread.currentThread().getName()+", "+this);
+ Thread.dumpStack();
+ }
+ _edtUtil.start();
+ }
+ }
+ }
+ if( !_edtUtil.isCurrentThreadEDT() ) {
+ if( _edtUtil.invoke(wait, task) ) {
+ return; // done
+ }
+ if( DEBUG ) {
+ System.err.println("Warning: invoke(wait "+wait+", ..) on EDT failed .. invoke on current thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
+ }
}
+ task.run();
}
- public boolean validateEDT() {
- if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
- stopEDT( new Runnable() {
- public void run() {
- // nop
+ @Override
+ public boolean validateEDTStopped() {
+ if( 0==refCount && null == aDevice ) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil && _edtUtil.isRunning() ) {
+ synchronized( this ) {
+ if( null != edtUtil && edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ stopEDT( edtUtil, null );
+ return true;
+ }
}
- } );
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- return true;
+ }
}
return false;
}
+ @Override
public synchronized final void destroy() {
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
}
synchronized(displayList) {
- displayList.remove(this);
if(0 < displaysActive) {
displaysActive--;
}
+ if(DEBUG) {
+ System.err.println("Display.destroy(): "+this+", active "+displaysActive+" "+getThreadName());
+ }
}
- if(DEBUG) {
- System.err.println("Display.destroy(): "+this+" "+getThreadName());
- }
- final AbstractGraphicsDevice f_aDevice = aDevice;
final DisplayImpl f_dpy = this;
- stopEDT( new Runnable() {
+ final AbstractGraphicsDevice f_aDevice = aDevice;
+ aDevice = null;
+ refCount=0;
+ stopEDT( edtUtil, new Runnable() { // blocks!
+ @Override
public void run() {
if ( null != f_aDevice ) {
- f_dpy.closeNativeImpl();
+ f_dpy.destroyAllPointerIconFromList(f_aDevice.getHandle());
+ f_dpy.closeNativeImpl(f_aDevice);
}
}
} );
- if(null!=edtUtil) {
- edtUtil.waitUntilStopped();
- edtUtil.reset();
- }
- aDevice = null;
- refCount=0;
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") END");
}
}
+ /** May be utilized at a shutdown hook, impl. does not block. */
+ /* pp */ static final void shutdownAll() {
+ final int dCount = displayList.size();
+ if(DEBUG) {
+ dumpDisplayList("Display.shutdownAll "+dCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<dCount && displayList.size()>0; i++) { // be safe ..
+ final DisplayImpl d = (DisplayImpl) displayList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Display.shutdownAll["+(i+1)+"/"+dCount+"]: "+d+", GCed "+(null==d));
+ }
+ if( null != d ) { // GC'ed ?
+ if(0 < displaysActive) {
+ displaysActive--;
+ }
+ final EDTUtil edtUtil = d.getEDTUtil();
+ final AbstractGraphicsDevice f_aDevice = d.aDevice;
+ d.aDevice = null;
+ d.refCount=0;
+ final Runnable closeNativeTask = new Runnable() {
+ @Override
+ public void run() {
+ if ( null != d.getGraphicsDevice() ) {
+ d.destroyAllPointerIconFromList(f_aDevice.getHandle());
+ d.closeNativeImpl(f_aDevice);
+ }
+ }
+ };
+ if(null != edtUtil) {
+ final long coopSleep = edtUtil.getPollPeriod() * 2;
+ if( edtUtil.isRunning() ) {
+ edtUtil.invokeStop(false, closeNativeTask); // don't block
+ }
+ try {
+ Thread.sleep( coopSleep < 50 ? coopSleep : 50 );
+ } catch (InterruptedException e) { }
+ } else {
+ closeNativeTask.run();
+ }
+ }
+ }
+ }
+
+ @Override
public synchronized final int addReference() {
if(DEBUG) {
System.err.println("Display.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
@@ -258,6 +539,7 @@ public abstract class DisplayImpl extends Display {
}
+ @Override
public synchronized final int removeReference() {
if(DEBUG) {
System.err.println("Display.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
@@ -270,29 +552,39 @@ public abstract class DisplayImpl extends Display {
return refCount;
}
+ @Override
public synchronized final int getReferenceCount() {
return refCount;
}
protected abstract void createNativeImpl();
- protected abstract void closeNativeImpl();
+ protected abstract void closeNativeImpl(AbstractGraphicsDevice aDevice);
+ @Override
public final int getId() {
return id;
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getName() {
return name;
}
+ @Override
public final String getFQName() {
return fqname;
}
+ @Override
+ public final boolean isExclusive() {
+ return exclusive;
+ }
+
public static final String nilString = "nil" ;
public String validateDisplayName(String name, long handle) {
@@ -311,9 +603,10 @@ public abstract class DisplayImpl extends Display {
sb.append(name);
sb.append("-");
sb.append(id);
- return sb.toString().intern();
+ return sb.toString();
}
+ @Override
public final long getHandle() {
if(null!=aDevice) {
return aDevice.getHandle();
@@ -321,65 +614,98 @@ public abstract class DisplayImpl extends Display {
return 0;
}
+ @Override
public final AbstractGraphicsDevice getGraphicsDevice() {
return aDevice;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aDevice;
}
+ protected final boolean isNativeValidAsync() {
+ return null != aDevice;
+ }
+ @Override
public boolean isEDTRunning() {
- if(null!=edtUtil) {
- return edtUtil.isRunning();
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil ) {
+ return _edtUtil.isRunning();
}
return false;
}
@Override
public String toString() {
- return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
+ final EDTUtil _edtUtil = edtUtil;
+ final boolean _edtUtilRunning = ( null != _edtUtil ) ? _edtUtil.isRunning() : false;
+ return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=_edtUtil)+", edtRunning "+_edtUtilRunning+", "+aDevice+"]";
}
+ /** 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;
- class DispatchMessagesRunnable implements Runnable {
+ final protected Runnable dispatchMessagesRunnable = new Runnable() {
+ @Override
public void run() {
DisplayImpl.this.dispatchMessages();
+ } };
+
+ final void dispatchMessage(final NEWTEvent event) {
+ try {
+ final Object source = event.getSource();
+ if(source instanceof NEWTEventConsumer) {
+ final NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
+ if(!consumer.consumeEvent(event)) {
+ // enqueue for later execution
+ enqueueEvent(false, event);
+ }
+ } else {
+ throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source);
+ }
+ } catch (Throwable t) {
+ final RuntimeException re;
+ if(t instanceof RuntimeException) {
+ re = (RuntimeException) t;
+ } else {
+ re = new RuntimeException(t);
+ }
+ throw re;
}
}
- DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable();
final void dispatchMessage(final NEWTEventTask eventTask) {
- NEWTEvent event = eventTask.get();
- if(null == event) {
- // Ooops ?
- System.err.println("Warning: event of eventTask is NULL");
- Thread.dumpStack();
- return;
- }
- Object source = event.getSource();
- if(source instanceof NEWTEventConsumer) {
- NEWTEventConsumer consumer = (NEWTEventConsumer) source ;
- if(!consumer.consumeEvent(event)) {
- // enqueue for later execution
- enqueueEvent(false, event);
+ final NEWTEvent event = eventTask.get();
+ try {
+ if(null == event) {
+ // Ooops ?
+ System.err.println("Warning: event of eventTask is NULL");
+ Thread.dumpStack();
+ return;
+ }
+ dispatchMessage(event);
+ } catch (RuntimeException re) {
+ if( eventTask.isCallerWaiting() ) {
+ // propagate exception to caller
+ eventTask.setException(re);
+ } else {
+ throw re;
}
- } else {
- throw new RuntimeException("Event source not NEWT: "+source.getClass().getName()+", "+source);
}
- eventTask.notifyIssuer();
+ eventTask.notifyCaller();
}
-
+
+ @Override
public void dispatchMessages() {
// System.err.println("Display.dispatchMessages() 0 "+this+" "+getThreadName());
- if(0==refCount || // no screens
+ if(0==refCount || // no screens
null==getGraphicsDevice() // no native device
- )
+ )
{
return;
}
@@ -408,23 +734,24 @@ public abstract class DisplayImpl extends Display {
}
public void enqueueEvent(boolean wait, NEWTEvent e) {
- if(!isEDTRunning()) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( !_edtUtil.isRunning() ) {
// oops .. we are already dead
if(DEBUG) {
- Throwable t = new Throwable("Warning: EDT already stopped: wait:="+wait+", "+e);
- t.printStackTrace();
+ System.err.println("Warning: EDT already stopped: wait:="+wait+", "+e);
+ Thread.dumpStack();
}
return;
}
-
- // can't wait if we are on EDT -> consume right away
- if(wait && edtUtil.isCurrentThreadEDT()) {
- dispatchMessage(new NEWTEventTask(e, null));
+
+ // can't wait if we are on EDT or NEDT -> consume right away
+ if(wait && _edtUtil.isCurrentThreadEDTorNEDT() ) {
+ dispatchMessage(e);
return;
}
-
- Object lock = new Object();
- NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null);
+
+ final Object lock = new Object();
+ final NEWTEventTask eTask = new NEWTEventTask(e, wait?lock:null);
synchronized(lock) {
synchronized(eventsLock) {
events.add(eTask);
@@ -437,36 +764,42 @@ public abstract class DisplayImpl extends Display {
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
+ if( null != eTask.getException() ) {
+ throw eTask.getException();
+ }
}
}
}
public interface DisplayRunnable<T> {
T run(long dpy);
- }
- public final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- final AbstractGraphicsDevice aDevice = getGraphicsDevice();
- if(null == aDevice) {
- throw new RuntimeException("null device - not initialized: "+this);
- }
+ }
+ public static final <T> T runWithLockedDevice(AbstractGraphicsDevice device, DisplayRunnable<T> action) {
T res;
- aDevice.lock();
+ device.lock();
try {
- res = action.run(aDevice.getHandle());
+ res = action.run(device.getHandle());
} finally {
- aDevice.unlock();
+ device.unlock();
}
return res;
}
-
- protected EDTUtil edtUtil = null;
+ public final <T> T runWithLockedDisplayDevice(DisplayRunnable<T> action) {
+ final AbstractGraphicsDevice device = getGraphicsDevice();
+ if(null == device) {
+ throw new RuntimeException("null device - not initialized: "+this);
+ }
+ return runWithLockedDevice(device, action);
+ }
+
+ protected volatile EDTUtil edtUtil = null;
protected int id;
protected String name;
protected String type;
protected String fqname;
protected int hashCode;
protected int refCount; // number of Display references by Screen
- protected boolean destroyWhenUnused;
+ protected boolean exclusive; // do not share this display, uses NullLock!
protected AbstractGraphicsDevice aDevice;
}
diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
new file mode 100644
index 000000000..9e10879c4
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
@@ -0,0 +1,147 @@
+/**
+ * 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;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+
+public class MonitorDeviceImpl extends MonitorDevice {
+
+ public MonitorDeviceImpl(ScreenImpl screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) {
+ super(screen, nativeId, sizeMM, viewport, currentMode, supportedModes);
+ }
+
+ @Override
+ public final MonitorMode queryCurrentMode() {
+ final ScreenImpl screenImpl = (ScreenImpl)screen;
+ final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+ sms.lock();
+ try {
+ final MonitorMode mm0 = screenImpl.queryCurrentMonitorModeIntern(this);
+ if(null == mm0) {
+ throw new InternalError("getCurrentMonitorModeIntern() == null");
+ }
+ MonitorMode mmU = supportedModes.get(mm0); // unified instance
+ if( null == mmU ) {
+ // add new mode avoiding exception!
+ mmU = sms.getMonitorModes().getOrAdd(mm0);
+ mmU = supportedModes.getOrAdd(mmU);
+ if( Screen.DEBUG ) {
+ System.err.println("Adding new mode: "+mm0+" -> "+mmU);
+ }
+ }
+ // if mode has changed somehow, update it ..
+ if( getCurrentMode().hashCode() != mmU.hashCode() ) {
+ setCurrentModeValue(mmU);
+ sms.fireMonitorModeChanged(this, mmU, true);
+ }
+ return mmU;
+ } finally {
+ sms.unlock();
+ }
+ }
+
+ @Override
+ public final boolean setCurrentMode(MonitorMode mode) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode.0: "+this+" -> "+mode);
+ }
+ final ScreenImpl screenImpl = (ScreenImpl)screen;
+ final ScreenMonitorState sms = screenImpl.getScreenMonitorStatus(true);
+ sms.lock();
+ try {
+ final MonitorMode mmC = queryCurrentMode();
+ final MonitorMode mmU = supportedModes.get(mode); // unify via value hash
+ if( null == mmU ) {
+ throw new IllegalArgumentException("Given mode not in set of modes. Current mode "+mode+", "+this);
+ }
+ if( mmU.equals( mmC ) ) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode: 0.0 is-current (skip) "+mmU+" == "+mmC);
+ }
+ return true;
+ }
+ final long tStart;
+ if(Screen.DEBUG) {
+ tStart = System.currentTimeMillis();
+ } else {
+ tStart = 0;
+ }
+
+ sms.fireMonitorModeChangeNotify(this, mmU);
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): fireModeChangeNotify() "+mmU);
+ }
+
+ boolean success = screenImpl.setCurrentMonitorModeImpl(this, mmU);
+ if(success) {
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(1): "+success);
+ }
+ } else {
+ // 2nd attempt validate!
+ final MonitorMode queriedCurrent = queryCurrentMode(); // may fireModeChanged(..) if successful and differs!
+ success = queriedCurrent.hashCode() == mmU.hashCode() ;
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode.2: queried "+queriedCurrent);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(2): "+success);
+ }
+ }
+ if( success ) {
+ setCurrentModeValue(mmU);
+ modeChanged = !isOriginalMode();
+ }
+ sms.fireMonitorModeChanged(this, mmU, success);
+ if(Screen.DEBUG) {
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): X.X: success "+success+": "+this);
+ }
+ return success;
+ } finally {
+ sms.unlock();
+ }
+ }
+
+ private final void setCurrentModeValue(MonitorMode currentMode) {
+ this.currentMode = currentMode;
+ }
+
+ /* pp */ final void setViewportValue(Rectangle viewport) {
+ this.viewport = viewport;
+ }
+
+ /* pp */ ArrayHashSet<MonitorMode> getSupportedModesImpl() {
+ return supportedModes;
+ }
+
+}
diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java
new file mode 100644
index 000000000..9d8f4919c
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java
@@ -0,0 +1,355 @@
+/**
+ * Copyright 2010 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;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.SurfaceSize;
+
+import jogamp.newt.MonitorDeviceImpl;
+import jogamp.newt.ScreenImpl;
+
+/**
+ * Encodes and decodes {@link MonitorMode} and {@link MonitorDevice} properties.
+ */
+public class MonitorModeProps {
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 2: width, height
+ */
+ public static final int NUM_RESOLUTION_PROPERTIES = 2;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 1: bpp
+ */
+ public static final int NUM_SURFACE_SIZE_PROPERTIES = 1;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 2: refresh-rate (Hz*100), flags
+ */
+ public static final int NUM_SIZEANDRATE_PROPERTIES = 2;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 2: id, rotation
+ */
+ public static final int NUM_MONITOR_MODE_PROPERTIES = 2;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * count + all the above
+ */
+ public static final int NUM_MONITOR_MODE_PROPERTIES_ALL = 8;
+
+ public static final int IDX_MONITOR_MODE_BPP = 1 // count
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+ ;
+ public static final int IDX_MONITOR_MODE_ROT = 1 // count
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES
+ + MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES
+ + MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES
+ + 1 // id of MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES
+ ;
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation
+ * 10: count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ */
+ public static final int MIN_MONITOR_DEVICE_PROPERTIES = 11;
+
+ public static final int IDX_MONITOR_DEVICE_VIEWPORT = 1 // count
+ + 1 // native mode
+ + MonitorModeProps.NUM_RESOLUTION_PROPERTIES // sizeMM
+ ;
+
+ public static class Cache {
+ public final ArrayHashSet<DimensionImmutable> resolutions = new ArrayHashSet<DimensionImmutable>();
+ public final ArrayHashSet<SurfaceSize> surfaceSizes = new ArrayHashSet<SurfaceSize>();
+ public final ArrayHashSet<MonitorMode.SizeAndRRate> sizeAndRates = new ArrayHashSet<MonitorMode.SizeAndRRate>();
+ public final ArrayHashSet<MonitorMode> monitorModes = new ArrayHashSet<MonitorMode>();
+ public final ArrayHashSet<MonitorDevice> monitorDevices = new ArrayHashSet<MonitorDevice>();
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static DimensionImmutable streamInResolution(int[] resolutionProperties, int offset) {
+ Dimension resolution = new Dimension(resolutionProperties[offset++], resolutionProperties[offset++]);
+ return resolution;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static SurfaceSize streamInSurfaceSize(DimensionImmutable resolution, int[] sizeProperties, int offset) {
+ SurfaceSize surfaceSize = new SurfaceSize(resolution, sizeProperties[offset++]);
+ return surfaceSize;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static MonitorMode.SizeAndRRate streamInSizeAndRRate(SurfaceSize surfaceSize, int[] sizeAndRRateProperties, int offset) {
+ final float refreshRate = sizeAndRRateProperties[offset++]/100.0f;
+ final int flags = sizeAndRRateProperties[offset++];
+ return new MonitorMode.SizeAndRRate(surfaceSize, refreshRate, flags);
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ private static MonitorMode streamInMonitorMode0(MonitorMode.SizeAndRRate sizeAndRate, int[] modeProperties, int offset) {
+ final int id = modeProperties[offset++];
+ final int rotation = modeProperties[offset++];
+ return new MonitorMode(id, sizeAndRate, rotation);
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ *
+ * @param mode_idx if not null and cache is given, returns the index of resulting {@link MonitorMode} within {@link Cache#monitorModes}.
+ * @param cache optional hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return {@link MonitorMode} of the identical (old or new) element in {@link Cache#monitorModes},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorMode streamInMonitorMode(int[] mode_idx, Cache cache,
+ int[] modeProperties, int offset) {
+ final int count = modeProperties[offset];
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL != count) {
+ throw new RuntimeException("property count should be "+NUM_MONITOR_MODE_PROPERTIES_ALL+", but is "+count+", len "+(modeProperties.length-offset));
+ }
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL > modeProperties.length-offset) {
+ throw new RuntimeException("properties array too short, should be >= "+NUM_MONITOR_MODE_PROPERTIES_ALL+", is "+(modeProperties.length-offset));
+ }
+ offset++;
+ DimensionImmutable resolution = MonitorModeProps.streamInResolution(modeProperties, offset);
+ offset += MonitorModeProps.NUM_RESOLUTION_PROPERTIES;
+ if(null!=cache) {
+ resolution = cache.resolutions.getOrAdd(resolution);
+ }
+
+ SurfaceSize surfaceSize = MonitorModeProps.streamInSurfaceSize(resolution, modeProperties, offset);
+ offset += MonitorModeProps.NUM_SURFACE_SIZE_PROPERTIES;
+ if(null!=cache) {
+ surfaceSize = cache.surfaceSizes.getOrAdd(surfaceSize);
+ }
+
+ MonitorMode.SizeAndRRate sizeAndRate = MonitorModeProps.streamInSizeAndRRate(surfaceSize, modeProperties, offset);
+ offset += MonitorModeProps.NUM_SIZEANDRATE_PROPERTIES;
+ if(null!=cache) {
+ sizeAndRate = cache.sizeAndRates.getOrAdd(sizeAndRate);
+ }
+
+ MonitorMode monitorMode = MonitorModeProps.streamInMonitorMode0(sizeAndRate, modeProperties, offset);
+ if(null!=cache) {
+ monitorMode = cache.monitorModes.getOrAdd(monitorMode);
+ }
+ if( null != mode_idx && null!=cache) {
+ int _modeIdx = cache.monitorModes.indexOf(monitorMode);
+ if( 0 > _modeIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorMode);
+ }
+ mode_idx[0] = _modeIdx;
+ }
+ return monitorMode;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static int[] streamOutMonitorMode (MonitorMode monitorMode) {
+ int[] data = new int[NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int idx=0;
+ data[idx++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ data[idx++] = monitorMode.getSurfaceSize().getResolution().getWidth();
+ data[idx++] = monitorMode.getSurfaceSize().getResolution().getHeight();
+ data[idx++] = monitorMode.getSurfaceSize().getBitsPerPixel();
+ data[idx++] = (int)(monitorMode.getRefreshRate()*100.0f); // Hz*100
+ data[idx++] = monitorMode.getFlags();
+ data[idx++] = monitorMode.getId();
+ data[idx++] = monitorMode.getRotation();
+ if(NUM_MONITOR_MODE_PROPERTIES_ALL != idx) {
+ throw new InternalError("wrong number of attributes: got "+idx+" != should "+NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ return data;
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * <p>
+ * Note: This variant only works for impl. w/ a unique mode key pair <i>modeId, rotation</i>.
+ * </p>
+ * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+ * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param modeProperties the input data
+ * @param offset the offset to the input data
+ * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, int[] monitorProperties, int offset) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ final int count = monitorProperties[offset];
+ if(MIN_MONITOR_DEVICE_PROPERTIES > count) {
+ throw new RuntimeException("property count should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", but is "+count+", len "+(monitorProperties.length-offset));
+ }
+ if(MIN_MONITOR_DEVICE_PROPERTIES > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (min), should be >= "+MIN_MONITOR_DEVICE_PROPERTIES+", is "+(monitorProperties.length-offset));
+ }
+ if(count > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+ }
+ final int limit = offset + count;
+ offset++;
+ final List<MonitorMode> allMonitorModes = cache.monitorModes.getData();
+ final int id = monitorProperties[offset++];
+ final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+ final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ final MonitorMode currentMode;
+ {
+ final int modeId = monitorProperties[offset++];
+ final int rotation = monitorProperties[offset++];
+ currentMode = getByNativeIdAndRotation(allMonitorModes, modeId, rotation);
+ }
+ final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ while( offset < limit ) {
+ final int modeId = monitorProperties[offset++];
+ for (int i=0; i<allMonitorModes.size(); i++) {
+ final MonitorMode mode = allMonitorModes.get(i);
+ if( mode.getId() == modeId ) {
+ supportedModes.add(mode);
+ }
+ }
+ }
+ MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewport, currentMode, supportedModes);
+ if(null!=cache) {
+ monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+ }
+ if( null != monitor_idx ) {
+ int _monitorIdx = cache.monitorDevices.indexOf(monitorDevice);
+ if( 0 > _monitorIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+ }
+ monitor_idx[0] = _monitorIdx;
+ }
+ return monitorDevice;
+ }
+ private static MonitorMode getByNativeIdAndRotation(List<MonitorMode> monitorModes, int modeId, int rotation) {
+ if( null!=monitorModes && monitorModes.size()>0 ) {
+ for (int i=0; i<monitorModes.size(); i++) {
+ final MonitorMode mode = monitorModes.get(i);
+ if( mode.getId() == modeId && mode.getRotation() == rotation ) {
+ return mode;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * WARNING: must be synchronized with ScreenMode.h, native implementation
+ * <p>
+ * This variant expects <code>count</code> to be <code>{@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}</code>,
+ * due to lack of supported mode and current mode.
+ * </p>
+ *
+ * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
+ * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
+ * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache.
+ * @param currentMode pre-fetched current {@link MonitorMode}s from cache.
+ * @param modeProperties the input data minus supported modes!
+ * @param offset the offset to the input data
+ * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
+ * matching the input <code>modeProperties</code>, or null if input could not be processed.
+ */
+ public static MonitorDevice streamInMonitorDevice(int[] monitor_idx, Cache cache, ScreenImpl screen, ArrayHashSet<MonitorMode> supportedModes, MonitorMode currentMode, int[] monitorProperties, int offset) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ final int count = monitorProperties[offset];
+ if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) {
+ throw new RuntimeException("property count should be == "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", but is "+count+", len "+(monitorProperties.length-offset));
+ }
+ if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (min), should be >= "+(MIN_MONITOR_DEVICE_PROPERTIES-1-NUM_MONITOR_MODE_PROPERTIES)+", is "+(monitorProperties.length-offset));
+ }
+ if(count > monitorProperties.length-offset) {
+ throw new RuntimeException("properties array too short (count), should be >= "+count+", is "+(monitorProperties.length-offset));
+ }
+ offset++;
+ final int id = monitorProperties[offset++];
+ final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
+ final Rectangle viewport = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewport, currentMode, supportedModes);
+ if(null!=cache) {
+ monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
+ }
+ if( null != monitor_idx ) {
+ int _monitorIdx = cache.monitorDevices.indexOf(monitorDevice);
+ if( 0 > _monitorIdx ) {
+ throw new InternalError("Invalid index of current unified mode "+monitorDevice);
+ }
+ monitor_idx[0] = _monitorIdx;
+ }
+ return monitorDevice;
+ }
+
+ /** WARNING: must be synchronized with ScreenMode.h, native implementation */
+ public static int[] streamOutMonitorDevice (MonitorDevice monitorDevice) {
+ // min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
+ int supportedModeCount = monitorDevice.getSupportedModes().size();
+ if( 0 == supportedModeCount ) {
+ throw new RuntimeException("no supported modes: "+monitorDevice);
+ }
+ int[] data = new int[MIN_MONITOR_DEVICE_PROPERTIES + supportedModeCount - 1];
+ int idx=0;
+ data[idx++] = data.length;
+ data[idx++] = monitorDevice.getId();
+ data[idx++] = monitorDevice.getSizeMM().getWidth();
+ data[idx++] = monitorDevice.getSizeMM().getHeight();
+ data[idx++] = monitorDevice.getViewport().getX();
+ data[idx++] = monitorDevice.getViewport().getY();
+ data[idx++] = monitorDevice.getViewport().getWidth();
+ data[idx++] = monitorDevice.getViewport().getHeight();
+ data[idx++] = monitorDevice.getCurrentMode().getId();
+ data[idx++] = monitorDevice.getCurrentMode().getRotation();
+ final List<MonitorMode> supportedModes = monitorDevice.getSupportedModes();
+ for(int i=0; i<supportedModes.size(); i++) {
+ data[idx++] = supportedModes.get(i).getId();
+ }
+ if(data.length != idx) {
+ throw new InternalError("wrong number of attributes: got "+idx+" != should "+data.length);
+ }
+ return data;
+ }
+
+ public final void swapRotatePair(int rotation, int[] pairs, int offset, int numPairs) {
+ if( MonitorMode.ROTATE_0 == rotation || MonitorMode.ROTATE_180 == rotation ) {
+ // nop
+ return;
+ }
+ for(int i=0; i<numPairs; i++, offset+=2) {
+ final int tmp = pairs[offset];
+ pairs[offset] = pairs[offset+1];
+ pairs[offset+1] = tmp;
+ }
+ }
+
+}
diff --git a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
index 2db9d8d05..9364ada30 100644
--- a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
+++ b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java
@@ -1,21 +1,21 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,11 +28,11 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
* You acknowledge that this software is not designed or intended for use
* in the design, construction, operation or maintenance of any nuclear
* facility.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -42,24 +42,24 @@ package jogamp.newt;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import jogamp.nativewindow.NWJNILibLoader;
+
import com.jogamp.common.jvm.JNILibLoaderBase;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.cache.TempJarCache;
public class NEWTJNILibLoader extends JNILibLoaderBase {
-
- public static void loadNEWT() {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Platform.initSingleton();
- final String libName = "newt";
- if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
- addNativeJarLibs(NEWTJNILibLoader.class, "jogl-all", new String[] { "nativewindow", "newt" } );
- }
- loadLibrary(libName, false, NEWTJNILibLoader.class.getClassLoader());
- return null;
- }
- });
- }
-
+ public static boolean loadNEWT() {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ Platform.initSingleton();
+ final String libName = "newt";
+ if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) {
+ JNILibLoaderBase.addNativeJarLibsJoglCfg(new Class<?>[] { NWJNILibLoader.class, NEWTJNILibLoader.class });
+ }
+ return Boolean.valueOf(loadLibrary(libName, false, NEWTJNILibLoader.class.getClassLoader()));
+ }
+ }).booleanValue();
+ }
}
diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java
index 050e24b6c..2478b1e5d 100644
--- a/src/newt/classes/jogamp/newt/OffscreenWindow.java
+++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,31 +29,42 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
-import javax.media.nativewindow.*;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
-public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
+import com.jogamp.newt.MonitorDevice;
+
+public class OffscreenWindow extends WindowImpl implements MutableSurface {
- long surfaceHandle = 0;
+ long surfaceHandle;
public OffscreenWindow() {
+ surfaceHandle = 0;
}
static long nextWindowHandle = 0x100; // start here - a marker
+ @Override
protected void createNativeImpl() {
if(capsRequested.isOnscreen()) {
throw new NativeWindowException("Capabilities is onscreen");
}
final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, aScreen);
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -62,22 +73,21 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
synchronized(OffscreenWindow.class) {
setWindowHandle(nextWindowHandle++);
}
+ visibleChanged(false, true);
}
+ @Override
protected void closeNativeImpl() {
// nop
}
- public void surfaceSizeChanged(int width, int height) {
- sizeChanged(false, width, height, false);
- }
-
@Override
public synchronized void destroy() {
super.destroy();
surfaceHandle = 0;
}
+ @Override
public void setSurfaceHandle(long handle) {
surfaceHandle = handle ;
}
@@ -87,6 +97,7 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
return surfaceHandle;
}
+ @Override
protected void requestFocusImpl(boolean reparented) {
}
@@ -94,16 +105,22 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
public void setPosition(int x, int y) {
// nop
}
-
+
@Override
public boolean setFullscreen(boolean fullscreen) {
- // nop
- return false;
+ return false; // nop
}
+ @Override
+ public boolean setFullscreen(List<MonitorDevice> monitors) {
+ return false; // nop
+ }
+
+
+ @Override
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ sizeChanged(false, width, height, false);
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- sizeChanged(false, width, height, false);
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
} else {
/**
@@ -120,19 +137,20 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
@Override
public Point getLocationOnScreen(Point storage) {
if(null!=storage) {
- storage.setX(0);
- storage.setY(0);
+ storage.set(0, 0);
return storage;
}
return new Point(0,0);
}
-
+
+ @Override
protected Point getLocationOnScreenImpl(int x, int y) {
return new Point(x,y);
}
-
+
+ @Override
protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ // nop ..
}
}
diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java
new file mode 100644
index 000000000..840799d55
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java
@@ -0,0 +1,171 @@
+/**
+ * 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;
+
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PointImmutable;
+
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
+
+public class PointerIconImpl implements PointerIcon {
+ private final DisplayImpl display;
+ private final PixelFormat pixelformat;
+ private final DimensionImmutable size;
+ private final ByteBuffer pixels;
+ private final PointImmutable hotspot;
+ private long handle;
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ public PointerIconImpl(final DisplayImpl display, final PixelFormat pixelformat, final DimensionImmutable size, final ByteBuffer pixels, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelformat;
+ this.size = size;
+ this.pixels = pixels;
+ this.hotspot = hotspot;
+
+ this.handle=handle;
+ }
+ public PointerIconImpl(final DisplayImpl display, final PixelRectangle pixelrect, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelrect.getPixelformat();
+ this.size = pixelrect.getSize();
+ this.pixels = pixelrect.getPixels();
+ this.hotspot = hotspot;
+ this.handle=handle;
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + display.getFQName().hashCode();
+ hash = ((hash << 5) - hash) + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + getStride();
+ hash = ((hash << 5) - hash) + ( isGLOriented() ? 1 : 0);
+ hash = ((hash << 5) - hash) + pixels.hashCode();
+ hashCode = ((hash << 5) - hash) + hotspot.hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
+
+ public synchronized final long getHandle() { return handle; }
+ public synchronized final long validatedHandle() {
+ synchronized(display.pointerIconList) {
+ if( !display.pointerIconList.contains(this) ) {
+ display.pointerIconList.add(this);
+ }
+ }
+ if( 0 == handle ) {
+ try {
+ handle = display.createPointerIconImpl(pixelformat, size.getWidth(), size.getHeight(), pixels, hotspot.getX(), hotspot.getY());
+ return handle;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ } else {
+ return handle;
+ }
+ }
+ @Override
+ public final Display getDisplay() { return display; }
+ @Override
+ public final PixelFormat getPixelformat() { return pixelformat; }
+ @Override
+ public final ByteBuffer getPixels() { return pixels; }
+ @Override
+ public synchronized final boolean isValid() { return 0 != handle; }
+ @Override
+ public synchronized final boolean validate() {
+ if( 0 == handle ) {
+ return 0 != validatedHandle();
+ }
+ return true;
+ }
+
+ @Override
+ public synchronized void destroy() {
+ if(DisplayImpl.DEBUG) {
+ System.err.println("PointerIcon.destroy: "+this+", "+display+", "+DisplayImpl.getThreadName());
+ }
+ if( 0 != handle ) {
+ synchronized(display.pointerIconList) {
+ display.pointerIconList.remove(this);
+ }
+ display.runOnEDTIfAvail(false, new Runnable() {
+ public void run() {
+ if( !display.isNativeValidAsync() ) {
+ destroyOnEDT(display.getHandle());
+ }
+ } } );
+ }
+ }
+
+ /** No checks, assume execution on EDT */
+ synchronized void destroyOnEDT(final long dpy) {
+ final long h = handle;
+ handle = 0;
+ try {
+ display.destroyPointerIconImpl(dpy, h);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public final DimensionImmutable getSize() {
+ return size;
+ }
+ @Override
+ public final int getStride() {
+ return size.getWidth() * pixelformat.bytesPerPixel();
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ @Override
+ public final PointImmutable getHotspot() {
+ return hotspot;
+ }
+ @Override
+ public final String toString() {
+ return "PointerIcon[obj 0x"+Integer.toHexString(super.hashCode())+", "+display.getFQName()+", 0x"+Long.toHexString(handle)+", "+pixelformat+", "+size+", "+hotspot+", pixels "+pixels+"]";
+ }
+} \ No newline at end of file
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index cf614b6f1..d7e6c641c 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,92 +29,72 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
-import javax.media.nativewindow.util.SurfaceSize;
-
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
-import com.jogamp.newt.util.MonitorMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public abstract class ScreenImpl extends Screen implements ScreenModeListener {
- protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
-
- protected static final int default_sm_bpp = 32;
- protected static final int default_sm_widthmm = 519;
- protected static final int default_sm_heightmm = 324;
- protected static final int default_sm_rate = 60;
- protected static final int default_sm_rotation = 0;
-
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+import com.jogamp.newt.util.MonitorModeUtil;
+
+public abstract class ScreenImpl extends Screen implements MonitorModeListener {
+ protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
+ }
+
+ public static final int default_sm_bpp = 32;
+ public static final int default_sm_widthmm = 519;
+ public static final int default_sm_heightmm = 324;
+ public static final int default_sm_rate = 60;
+ public static final int default_sm_rotation = 0;
+
+ static {
+ DisplayImpl.initSingleton();
+ }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
protected DisplayImpl display;
protected int screen_idx;
protected String fqname;
protected int hashCode;
protected AbstractGraphicsScreen aScreen;
protected int refCount; // number of Screen references by Window
- protected Point vOrigin = new Point(0, 0); // virtual top-left origin
- protected Dimension vSize = new Dimension(0, 0); // virtual rotated screen size
+ protected Rectangle vOriginSize = new Rectangle(0, 0, 0, 0); // virtual rotated screen origin and size
protected static Dimension usrSize = null; // property values: newt.ws.swidth and newt.ws.sheight
protected static volatile boolean usrSizeQueried = false;
- private ArrayList<ScreenModeListener> referencedScreenModeListener = new ArrayList<ScreenModeListener>();
+ private ArrayList<MonitorModeListener> refMonitorModeListener = new ArrayList<MonitorModeListener>();
+
private long tCreated; // creationTime
- static {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- registerShutdownHook();
- return null;
- }
- });
- }
-
- @SuppressWarnings("unchecked")
- private static Class<? extends Screen> getScreenClass(String type) throws ClassNotFoundException
+ private static Class<?> getScreenClass(String type) throws ClassNotFoundException
{
- Class<?> screenClass = NewtFactory.getCustomClass(type, "Screen");
+ final Class<?> screenClass = NewtFactory.getCustomClass(type, "ScreenDriver");
if(null==screenClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- screenClass = Class.forName("jogamp.newt.driver.android.AndroidScreen");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- screenClass = Class.forName("jogamp.newt.driver.kd.KDScreen");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- screenClass = Class.forName("jogamp.newt.driver.windows.WindowsScreen");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- screenClass = Class.forName("jogamp.newt.driver.macosx.MacScreen");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- screenClass = Class.forName("jogamp.newt.driver.x11.X11Screen");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- screenClass = Class.forName("jogamp.newt.driver.awt.AWTScreen");
- } else {
- throw new RuntimeException("Unknown window type \"" + type + "\"");
- }
+ throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".ScreenDriver>");
}
- if(null==screenClass) {
- throw new ClassNotFoundException("Failed to find NEWT Screen Class <"+type+".Screen>");
- }
- return (Class<? extends Screen>)screenClass;
+ return screenClass;
}
public static Screen create(Display display, int idx) {
@@ -124,7 +104,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
if(!usrSizeQueried) {
usrSizeQueried = true;
final int w = Debug.getIntProperty("newt.ws.swidth", true, 0);
- final int h = Debug.getIntProperty("newt.ws.sheight", true, 0);
+ final int h = Debug.getIntProperty("newt.ws.sheight", true, 0);
if(w>0 && h>0) {
usrSize = new Dimension(w, h);
System.err.println("User screen size "+usrSize);
@@ -133,7 +113,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
}
synchronized(screenList) {
- Class<? extends Screen> screenClass = getScreenClass(display.getType());
+ Class<?> screenClass = getScreenClass(display.getType());
ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
screen.display = (DisplayImpl) display;
idx = screen.validateScreenIndex(idx);
@@ -148,14 +128,14 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
}
screen.screen_idx = idx;
- screen.fqname = (display.getFQName()+idx).intern();
+ screen.fqname = display.getFQName()+"-s"+idx;
screen.hashCode = screen.fqname.hashCode();
- screenList.add(screen);
+ Screen.addScreen2List(screen);
if(DEBUG) {
System.err.println("Screen.create() NEW: "+screen+" "+Display.getThreadName());
}
return screen;
- }
+ }
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -179,13 +159,15 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
return true;
}
+ @Override
public int hashCode() {
return hashCode;
}
+ @Override
public synchronized final void createNative()
throws NativeWindowException
- {
+ {
if(null == aScreen) {
if(DEBUG) {
tCreated = System.nanoTime();
@@ -193,38 +175,38 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
} else {
tCreated = 0;
}
-
display.addReference();
-
+
createNativeImpl();
if(null == aScreen) {
throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
}
-
- initScreenModeStatus();
- updateVirtualScreenOriginAndSize();
- if(DEBUG) {
- System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
- }
+
+ initMonitorState();
synchronized(screenList) {
screensActive++;
+ if(DEBUG) {
+ System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), active "+screensActive+", total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
+ }
}
+ ScreenMonitorState.getScreenMonitorState(this.getFQName()).addListener(this);
}
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- sms.addListener(this);
}
+ @Override
public synchronized final void destroy() {
- releaseScreenModeStatus();
-
synchronized(screenList) {
- screenList.remove(this);
if(0 < screensActive) {
screensActive--;
}
+ if(DEBUG) {
+ System.err.println("Screen.destroy() ("+DisplayImpl.getThreadName()+"): active "+screensActive);
+ // Thread.dumpStack();
+ }
}
if ( null != aScreen ) {
+ releaseMonitorState();
closeNativeImpl();
aScreen = null;
}
@@ -232,6 +214,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
display.removeReference();
}
+ @Override
public synchronized final int addReference() throws NativeWindowException {
if(DEBUG) {
System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1));
@@ -239,13 +222,13 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
}
if ( 0 == refCount ) {
createNative();
- }
- if(null == aScreen) {
+ } else if(null == aScreen) {
throw new NativeWindowException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen");
}
return ++refCount;
}
+ @Override
public synchronized final int removeReference() {
if(DEBUG) {
System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
@@ -259,13 +242,14 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
return refCount;
}
+ @Override
public synchronized final int getReferenceCount() {
return refCount;
}
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
-
+
/**
* Returns the validated screen index, which is either the passed <code>idx</code>
* value or <code>0</code>.
@@ -274,18 +258,24 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
* </p>
*/
protected abstract int validateScreenIndex(int idx);
-
+
/**
* Stores the virtual origin and virtual <b>rotated</b> screen size.
* <p>
- * This method is called after the ScreenMode has been set,
+ * This method is called after the MonitorMode has been set or changed,
* hence you may utilize it.
- * </p>
- * @param virtualOrigin the store for the virtual origin
- * @param virtualSize the store for the virtual rotated size
+ * </p>
+ * <p>
+ * Default implementation uses the union of all monitor's viewport,
+ * calculated via {@link #unionOfMonitorViewportSize()}.
+ * </p>
+ * @param vOriginSize storage for result
*/
- protected abstract void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize);
-
+ protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) {
+ unionOfMonitorViewportSize(vOriginSize);
+ }
+
+ @Override
public final String getFQName() {
return fqname;
}
@@ -294,401 +284,399 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
* Updates the <b>rotated</b> virtual ScreenSize using the native impl.
*/
protected void updateVirtualScreenOriginAndSize() {
- getVirtualScreenOriginAndSize(vOrigin, vSize);
- if(DEBUG) {
- System.err.println("Detected screen origin "+vOrigin+", size "+vSize);
+ if(null != usrSize ) {
+ vOriginSize.set(0, 0, usrSize.getWidth(), usrSize.getHeight());
+ if(DEBUG) {
+ System.err.println("Update user virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize);
+ }
+ } else {
+ calcVirtualScreenOriginAndSize(vOriginSize);
+ if(DEBUG) {
+ System.err.println("Updated virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize);
+ }
}
}
+ @Override
public final Display getDisplay() {
return display;
}
+ @Override
public final int getIndex() {
return screen_idx;
}
+ @Override
public final AbstractGraphicsScreen getGraphicsScreen() {
return aScreen;
}
+ @Override
public synchronized final boolean isNativeValid() {
return null != aScreen;
}
- public int getX() { return vOrigin.getX(); }
- public int getY() { return vOrigin.getY(); }
-
- public final int getWidth() {
- return (null != usrSize) ? usrSize.getWidth() : vSize.getWidth();
- }
-
- public final int getHeight() {
- return (null != usrSize) ? usrSize.getHeight() : vSize.getHeight();
- }
+ @Override
+ public final int getX() { return vOriginSize.getX(); }
+ @Override
+ public final int getY() { return vOriginSize.getY(); }
+ @Override
+ public final int getWidth() { return vOriginSize.getWidth(); }
+ @Override
+ public final int getHeight() { return vOriginSize.getHeight(); }
+ @Override
+ public final RectangleImmutable getViewport() { return vOriginSize; }
@Override
public String toString() {
- return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", "+getWidth()+"x"+getHeight()+", "+aScreen+", "+display+"]";
+ return "NEWT-Screen["+getFQName()+", idx "+screen_idx+", refCount "+refCount+", vsize "+vOriginSize+", "+aScreen+", "+display+
+ ", monitors: "+getMonitorDevices()+"]";
}
- public final List<ScreenMode> getScreenModes() {
- ArrayHashSet<ScreenMode> screenModes = getScreenModesOrig();
- if(null != screenModes && 0 < screenModes.size()) {
- return screenModes.toArrayList();
- }
- return null;
- }
+ //
+ // MonitorDevice and MonitorMode
+ //
- public ScreenMode getOriginalScreenMode() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- return ( null != sms ) ? sms.getOriginalScreenMode() : null ;
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * Is called only to collect the {@link MonitorMode}s and {@link MonitorDevice}s, usually at startup setting up modes.<br>
+ * <br>
+ * <b>WARNING</b>: must be synchronized with
+ * <ul>
+ * <li>{@link MonitorModeProps#NUM_SCREEN_MODE_PROPERTIES} and </li>
+ * <li>{@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}</li>
+ * </ul>, i.e.
+ * <ul>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li>
+ * </ul>
+ * @param cache memory pool caching the result
+ */
+ protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache);
+
+ protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) { return null; }
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ * <p>
+ * Implementation shall not unify the result w/ monitor's supported modes or a locally
+ * saved {@link MonitorModeProps.Cache}, since caller will perform such tasks.
+ * </p>
+ */
+ protected abstract MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor);
+
+ /**
+ * To be implemented by the native specification.<br>
+ * Is called within a thread safe environment.<br>
+ */
+ protected abstract boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode);
+
+ @Override
+ public final List<MonitorMode> getMonitorModes() {
+ final ScreenMonitorState sms = getScreenMonitorStatus(false);
+ return null != sms ? sms.getMonitorModes().getData() : null;
}
- public ScreenMode getCurrentScreenMode() {
- ScreenMode smU = null;
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null == sms) {
- throw new InternalError("ScreenModeStatus.getScreenModeStatus("+this.getFQName()+") == null");
- }
- ScreenMode sm0 = getCurrentScreenModeIntern();
- if(null == sm0) {
- throw new InternalError("getCurrentScreenModeImpl() == null");
- }
- sms.lock();
- try {
- smU = sms.getScreenModes().getOrAdd(sm0); // unified instance, maybe new
+ @Override
+ public final List<MonitorDevice> getMonitorDevices() {
+ final ScreenMonitorState sms = getScreenMonitorStatus(false);
+ return null != sms ? sms.getMonitorDevices().getData() : null;
+ }
- // if mode has changed somehow, update it ..
- if( sms.getCurrentScreenMode().hashCode() != smU.hashCode() ) {
- sms.fireScreenModeChanged(smU, true);
- }
- } finally {
- sms.unlock();
+ final ScreenMonitorState getScreenMonitorStatus(boolean throwException) {
+ final String key = this.getFQName();
+ final ScreenMonitorState res = ScreenMonitorState.getScreenMonitorState(key);
+ if(null == res & throwException) {
+ throw new InternalError("ScreenMonitorStatus.getMonitorModeStatus("+key+") == null");
}
- return smU;
+ return res;
}
- public boolean setCurrentScreenMode(ScreenMode screenMode) {
- final ScreenMode smC = getCurrentScreenMode();
- ScreenMode smU = getScreenModesOrig().get(screenMode); // unify via value hash
- if(smU.equals(smC)) {
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tCreated)+"): 0.0 is-current (skip) "+smU+" == "+smC);
- }
- return true;
+ @Override
+ public void monitorModeChangeNotify(MonitorEvent me) {
+ if(DEBUG) {
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": "+me);
}
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null == sms) {
- throw new InternalError("ScreenModeStatus.getScreenModeStatus("+this.getFQName()+") == null");
+ for(int i=0; i<refMonitorModeListener.size(); i++) {
+ ((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChangeNotify(me);
}
- boolean success;
- sms.lock();
- try {
- final long tStart;
- if(DEBUG) {
- tStart = System.nanoTime();
- } else {
- tStart = 0;
- }
-
- sms.fireScreenModeChangeNotify(smU);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireScreenModeChangeNotify() "+smU);
- }
+ }
- success = setCurrentScreenModeImpl(smU);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentScreenModeImpl() "+smU+", success: "+success);
+ private void updateNativeMonitorDevicesViewport() {
+ final List<MonitorDevice> monitors = getMonitorDevices();
+ for(int i=monitors.size()-1; i>=0; i--) {
+ final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i);
+ final Rectangle newViewport = getNativeMonitorDeviceViewportImpl(monitor);
+ if( DEBUG ) {
+ System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": "+monitor.getViewport()+" -> "+newViewport);
}
-
- sms.fireScreenModeChanged(smU, success);
- if(DEBUG) {
- System.err.println("Screen.setCurrentScreenMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+smU+", success: "+success);
+ if( null != newViewport ) {
+ monitor.setViewportValue(newViewport);
}
- } finally {
- sms.unlock();
}
- return success;
}
- public void screenModeChangeNotify(ScreenMode sm) {
- for(int i=0; i<referencedScreenModeListener.size(); i++) {
- ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChangeNotify(sm);
- }
- }
-
- public void screenModeChanged(ScreenMode sm, boolean success) {
+ @Override
+ public void monitorModeChanged(MonitorEvent me, boolean success) {
if(success) {
+ updateNativeMonitorDevicesViewport();
updateVirtualScreenOriginAndSize();
}
- for(int i=0; i<referencedScreenModeListener.size(); i++) {
- ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success);
+ if(DEBUG) {
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": success "+success+", "+me);
}
- }
-
- public synchronized final void addScreenModeListener(ScreenModeListener sml) {
- referencedScreenModeListener.add(sml);
- }
-
- public synchronized final void removeScreenModeListener(ScreenModeListener sml) {
- referencedScreenModeListener.remove(sml);
- }
-
- /** ScreenModeStatus bridge to native implementation */
- protected final ArrayHashSet<ScreenMode> getScreenModesOrig() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null!=sms) {
- return sms.getScreenModes();
+ for(int i=0; i<refMonitorModeListener.size(); i++) {
+ ((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChanged(me, success);
}
- return null;
}
- /** ScreenModeStatus bridge to native implementation */
- protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null!=sms) {
- return sms.getScreenModesIdx2NativeIdx();
- }
- return null;
+ @Override
+ public synchronized final void addMonitorModeListener(MonitorModeListener sml) {
+ refMonitorModeListener.add(sml);
}
- /**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
- * <br>
- * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
- * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
- * <br>
- * <b>Note</b>: Additional 1st element is native mode id.
- */
- protected int[] getScreenModeFirstImpl() {
- return null;
+ @Override
+ public synchronized final void removeMonitorModeListener(MonitorModeListener sml) {
+ refMonitorModeListener.remove(sml);
}
/**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- * Is called only to collect the ScreenModes, usually at startup setting up modes.<br>
- * <br>
- * <b>WARNING</b>: must be synchronized with {@link com.jogamp.newt.util.ScreenModeUtil#NUM_SCREEN_MODE_PROPERTIES},
- * ie {@link com.jogamp.newt.util.ScreenModeUtil#streamIn(com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, com.jogamp.common.util.ArrayHashSet, int[], int)}<br>
- * <br>
- * <b>Note</b>: Additional 1st element is native mode id.
+ *
+ * @param cache optional ..
+ * @param modeId
+ * @return
*/
- protected int[] getScreenModeNextImpl() {
- return null;
+ private final MonitorMode getVirtualMonitorMode(MonitorModeProps.Cache cache, int modeId) {
+ final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = getWidth(); // width
+ props[i++] = getHeight(); // height
+ props[i++] = default_sm_bpp;
+ props[i++] = default_sm_rate * 100;
+ props[i++] = 0; // flags
+ props[i++] = modeId;
+ props[i++] = default_sm_rotation;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
}
/**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
+ *
+ * @param cache mandatory !
+ * @param monitorId
+ * @param currentMode
+ * @return
*/
- protected ScreenMode getCurrentScreenModeImpl() {
- return null;
+ private final MonitorDevice getVirtualMonitorDevice(MonitorModeProps.Cache cache, int monitorId, MonitorMode currentMode) {
+ int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES];
+ int i = 0;
+ props[i++] = MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES;
+ props[i++] = monitorId;
+ props[i++] = default_sm_widthmm;
+ props[i++] = default_sm_heightmm;
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+ props[i++] = currentMode.getId(); // current mode id
+ props[i++] = currentMode.getRotation();
+ props[i++] = currentMode.getId(); // supported mode id #1
+ if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) {
+ throw new InternalError("XX");
+ }
+ return MonitorModeProps.streamInMonitorDevice(null, cache, this, props, 0);
}
-
+
/**
- * Utilizes {@link #getCurrentScreenModeImpl()}, if the latter returns null it uses
+ * Utilizes {@link #getCurrentMonitorModeImpl()}, if the latter returns null it uses
* the current screen size and dummy values.
*/
- protected ScreenMode getCurrentScreenModeIntern() {
- ScreenMode res;
+ protected final MonitorMode queryCurrentMonitorModeIntern(MonitorDevice monitor) {
+ MonitorMode res;
if(DEBUG_TEST_SCREENMODE_DISABLED) {
res = null;
} else {
- res = getCurrentScreenModeImpl();
+ res = queryCurrentMonitorModeImpl(monitor);
}
if(null == res) {
- if( 0==getWidth()*getHeight() ) {
+ if( 0>=getWidth() || 0>=getHeight() ) {
updateVirtualScreenOriginAndSize();
}
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int i = 0;
- props[i++] = 0; // set later for verification of iterator
- props[i++] = getWidth(); // width
- props[i++] = getHeight(); // height
- props[i++] = default_sm_bpp;
- props[i++] = default_sm_widthmm;
- props[i++] = default_sm_heightmm;
- props[i++] = default_sm_rate;
- props[i++] = default_sm_rotation;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
- res = ScreenModeUtil.streamIn(props, 0);
+ res = getVirtualMonitorMode(null, monitor.getCurrentMode().getId());
}
return res;
}
- /**
- * To be implemented by the native specification.<br>
- * Is called within a thread safe environment.<br>
- */
- protected boolean setCurrentScreenModeImpl(ScreenMode screenMode) {
- return false;
- }
-
- private ScreenModeStatus initScreenModeStatus() {
+ private final ScreenMonitorState initMonitorState() {
long t0;
if(DEBUG) {
t0 = System.nanoTime();
- System.err.println("Screen.initScreenModeStatus() START ("+DisplayImpl.getThreadName()+", "+this+")");
+ System.err.println("Screen.initMonitorState() START ("+DisplayImpl.getThreadName()+", "+this+")");
} else {
t0 = 0;
}
- ScreenModeStatus sms;
- ScreenModeStatus.lockScreenModeStatus();
+ boolean vScrnSizeUpdated = false;
+ ScreenMonitorState sms;
+ ScreenMonitorState.lockScreenMonitorState();
try {
- sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
- if(null==sms) {
- IntIntHashMap screenModesIdx2NativeIdx = new IntIntHashMap();
- final ScreenMode currentSM = getCurrentScreenModeIntern();
- if(null == currentSM) {
- throw new InternalError("getCurrentScreenModeImpl() == null");
+ sms = ScreenMonitorState.getScreenMonitorState(this.getFQName());
+ if(null==sms) {
+ final MonitorModeProps.Cache cache = new MonitorModeProps.Cache();
+ if( 0 >= collectNativeMonitorModes(cache) ) {
+ updateVirtualScreenOriginAndSize();
+ vScrnSizeUpdated = true;
+ final MonitorMode mode = getVirtualMonitorMode(cache, 0);
+ cache.monitorModes.getOrAdd(mode);
+ final MonitorDevice monitor = getVirtualMonitorDevice(cache, 0, mode);
+ cache.monitorDevices.getOrAdd(monitor);
+ }
+ // Sort MonitorModes (all and per device) in descending order - default!
+ MonitorModeUtil.sort(cache.monitorModes.getData(), false ); // descending order
+ for(Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); ) {
+ MonitorModeUtil.sort(iMonitor.next().getSupportedModes(), false ); // descending order
}
-
- ArrayHashSet<ScreenMode> screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx);
- screenModes.getOrAdd(currentSM);
if(DEBUG) {
int i=0;
- for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) {
- System.err.println(i+": "+iter.next());
+ for(Iterator<MonitorMode> iMode=cache.monitorModes.iterator(); iMode.hasNext(); i++) {
+ System.err.println("All["+i+"]: "+iMode.next());
+ }
+ i=0;
+ for(Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); i++) {
+ final MonitorDevice crt = iMonitor.next();
+ System.err.println("["+i+"]: "+crt);
+ int j=0;
+ for(Iterator<MonitorMode> iMode=crt.getSupportedModes().iterator(); iMode.hasNext(); j++) {
+ System.err.println("["+i+"]["+j+"]: "+iMode.next());
+ }
}
}
-
- sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx);
- ScreenMode originalScreenMode0 = screenModes.get(currentSM); // unify via value hash
- if(null == originalScreenMode0) {
- throw new RuntimeException(currentSM+" could not be hashed from ScreenMode list");
- }
- sms.setOriginalScreenMode(originalScreenMode0);
- ScreenModeStatus.mapScreenModeStatus(this.getFQName(), sms);
+ sms = new ScreenMonitorState(cache.monitorDevices, cache.monitorModes);
+ ScreenMonitorState.mapScreenMonitorState(this.getFQName(), sms);
}
} finally {
- ScreenModeStatus.unlockScreenModeStatus();
+ ScreenMonitorState.unlockScreenMonitorState();
}
if(DEBUG) {
- System.err.println("Screen.initScreenModeStatus() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
+ System.err.println("Screen.initMonitorState() END dt "+ (System.nanoTime()-t0)/1e6 +"ms");
}
+ if( !vScrnSizeUpdated ) {
+ updateVirtualScreenOriginAndSize();
+ }
+
return sms;
}
- /** ignores bpp < 15 */
- private ArrayHashSet<ScreenMode> collectNativeScreenModes(IntIntHashMap screenModesIdx2NativeId) {
- ArrayHashSet<DimensionImmutable> resolutionPool = new ArrayHashSet<DimensionImmutable>();
- ArrayHashSet<SurfaceSize> surfaceSizePool = new ArrayHashSet<SurfaceSize>();
- ArrayHashSet<DimensionImmutable> screenSizeMMPool = new ArrayHashSet<DimensionImmutable>();
- ArrayHashSet<MonitorMode> monitorModePool = new ArrayHashSet<MonitorMode>();
- ArrayHashSet<ScreenMode> screenModePool = new ArrayHashSet<ScreenMode>();
-
- int[] smProps = null;
- int num = 0;
- final int idxBpp = 1 // native mode
- + 1 // count
- + ScreenModeUtil.NUM_RESOLUTION_PROPERTIES
- + ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES
- - 1 ; // index 0 based
- do {
- if(DEBUG_TEST_SCREENMODE_DISABLED) {
- smProps = null;
- } else if(0 == num) {
- smProps = getScreenModeFirstImpl();
- } else {
- smProps = getScreenModeNextImpl();
- }
- if(null != smProps && 0 < smProps.length && smProps[idxBpp] >= 15) {
- int nativeId = smProps[0];
- int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool,
- monitorModePool, screenModePool, smProps, 1);
- if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": idx: "+nativeId+" native -> "+screenModeIdx+" newt");
+ /**
+ * Returns the number of successful collected {@link MonitorDevice}s.
+ * <p>
+ * Collects {@link MonitorDevice}s and {@link MonitorMode}s within the given cache.
+ * </p>
+ */
+ private final int collectNativeMonitorModes(MonitorModeProps.Cache cache) {
+ if(!DEBUG_TEST_SCREENMODE_DISABLED) {
+ collectNativeMonitorModesAndDevicesImpl(cache);
+ }
+ // filter out insufficient modes
+ for(int i=cache.monitorModes.size()-1; i>=0; i--) {
+ final MonitorMode mode = cache.monitorModes.get(i);
+ if( 16 > mode.getSurfaceSize().getBitsPerPixel() ) {
+ boolean keep = false;
+ for(int j=cache.monitorDevices.size()-1; !keep && j>=0; j--) {
+ final MonitorDevice monitor = cache.monitorDevices.get(j);
+ keep = monitor.getCurrentMode().equals(mode);
}
-
- if(screenModeIdx >= 0) {
- screenModesIdx2NativeId.put(screenModeIdx, nativeId);
+ if(!keep) {
+ cache.monitorModes.remove(i);
+ for(int j=cache.monitorDevices.size()-1; j>=0; j--) {
+ final MonitorDeviceImpl monitor = (MonitorDeviceImpl) cache.monitorDevices.get(j);
+ monitor.getSupportedModesImpl().remove(mode);
+ }
}
- } else if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": smProps: "+(null!=smProps)+
- ", len: "+(null != smProps ? smProps.length : 0)+
- ", bpp: "+(null != smProps && 0 < smProps.length ? smProps[idxBpp] : 0)+
- " - DROPPING");
}
- num++;
- } while ( null != smProps && 0 < smProps.length );
-
- if(DEBUG) {
- System.err.println("ScreenImpl.collectNativeScreenModes: ScreenMode number : "+screenModePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: MonitorMode number : "+monitorModePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: ScreenSizeMM number: "+screenSizeMMPool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: SurfaceSize number : "+surfaceSizePool.size());
- System.err.println("ScreenImpl.collectNativeScreenModes: Resolution number : "+resolutionPool.size());
}
-
- return screenModePool;
+ if( DEBUG ) {
+ System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorDevice number : "+cache.monitorDevices.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: MonitorMode number : "+cache.monitorModes.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: SizeAndRate number : "+cache.sizeAndRates.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: SurfaceSize number : "+cache.surfaceSizes.size());
+ System.err.println("ScreenImpl.collectNativeMonitorModes: Resolution number : "+cache.resolutions.size());
+ }
+ return cache.monitorDevices.size();
}
- private void releaseScreenModeStatus() {
- ScreenModeStatus sms;
- ScreenModeStatus.lockScreenModeStatus();
+ private final void releaseMonitorState() {
+ ScreenMonitorState sms;
+ ScreenMonitorState.lockScreenMonitorState();
try {
- sms = ScreenModeStatus.getScreenModeStatus(getFQName());
+ sms = ScreenMonitorState.getScreenMonitorState(getFQName());
if(null != sms) {
sms.lock();
try {
if(0 == sms.removeListener(this)) {
- if(sms.isOriginalModeChangedByOwner()) {
- System.err.println("Screen.destroy(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
- try {
- setCurrentScreenMode(sms.getOriginalScreenMode());
- } catch (Throwable t) {
- // be verbose but continue
- t.printStackTrace();
+ final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+ for(int i=0; i<monitorDevices.size(); i++) {
+ final MonitorDevice monitor = monitorDevices.get(i);
+ if( monitor.isModeChangedByUs() ) {
+ System.err.println("Screen.destroy(): Reset "+monitor);
+ try {
+ monitor.setCurrentMode(monitor.getOriginalMode());
+ } catch (Throwable t) {
+ // be verbose but continue
+ t.printStackTrace();
+ }
}
}
- ScreenModeStatus.unmapScreenModeStatus(getFQName());
+ ScreenMonitorState.unmapScreenMonitorState(getFQName());
}
} finally {
sms.unlock();
}
- }
+ }
} finally {
- ScreenModeStatus.unlockScreenModeStatus();
+ ScreenMonitorState.unlockScreenMonitorState();
}
}
-
+
private final void shutdown() {
- ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatusUnlocked(getFQName());
+ ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorStateUnlocked(getFQName());
if(null != sms) {
- if(sms.isOriginalModeChangedByOwner()) {
- try {
- System.err.println("Screen.shutdown(): "+sms.getCurrentScreenMode()+" -> "+sms.getOriginalScreenMode());
- setCurrentScreenModeImpl(sms.getOriginalScreenMode());
- } catch (Throwable t) {
- // be quiet .. shutdown
+ final ArrayList<MonitorDevice> monitorDevices = sms.getMonitorDevices().getData();
+ for(int i=0; i<monitorDevices.size(); i++) {
+ final MonitorDevice monitor = monitorDevices.get(i);
+ if( monitor.isModeChangedByUs() ) {
+ System.err.println("Screen.shutdown(): Reset "+monitor);
+ try {
+ monitor.setCurrentMode(monitor.getOriginalMode());
+ } catch (Throwable t) {
+ // be quiet .. shutdown
+ }
}
}
- ScreenModeStatus.unmapScreenModeStatusUnlocked(getFQName());
- }
- }
- private static final void shutdownAll() {
- for(int i=0; i < screenList.size(); i++) {
- ((ScreenImpl)screenList.get(i)).shutdown();
+ ScreenMonitorState.unmapScreenMonitorStateUnlocked(getFQName());
}
}
-
- private static synchronized void registerShutdownHook() {
- final Thread shutdownHook = new Thread(new Runnable() {
- public void run() {
- ScreenImpl.shutdownAll();
+
+ /** pp */ static final void shutdownAll() {
+ final int sCount = screenList.size();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll "+sCount+" instances, on thread "+Display.getThreadName());
+ }
+ for(int i=0; i<sCount && screenList.size()>0; i++) { // be safe ..
+ final ScreenImpl s = (ScreenImpl) screenList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll["+(i+1)+"/"+sCount+"]: "+s+", GCed "+(null==s));
}
- });
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- return null;
+ if( null != s ) {
+ s.shutdown();
}
- });
+ }
}
}
-
diff --git a/src/newt/classes/jogamp/newt/ScreenModeStatus.java b/src/newt/classes/jogamp/newt/ScreenModeStatus.java
deleted file mode 100644
index 4075fb131..000000000
--- a/src/newt/classes/jogamp/newt/ScreenModeStatus.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * Copyright 2010 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;
-
-import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-import com.jogamp.newt.Screen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.event.ScreenModeListener;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class ScreenModeStatus {
- private static boolean DEBUG = Screen.DEBUG;
-
- private RecursiveLock lock = LockFactory.createRecursiveLock();
- private ArrayHashSet<ScreenMode> screenModes;
- private IntIntHashMap screenModesIdx2NativeIdx;
- private ScreenMode currentScreenMode;
- private ScreenMode originalScreenMode;
- private boolean screenModeChangedByOwner;
- private ArrayList<ScreenModeListener> listener = new ArrayList<ScreenModeListener>();
-
- private static HashMap<String, ScreenModeStatus> screenFQN2ScreenModeStatus = new HashMap<String, ScreenModeStatus>();
- private static RecursiveLock screen2ScreenModeStatusLock = LockFactory.createRecursiveLock();
-
- protected static void mapScreenModeStatus(String screenFQN, ScreenModeStatus sms) {
- screen2ScreenModeStatusLock.lock();
- try {
- ScreenModeStatus _sms = screenFQN2ScreenModeStatus.get(screenFQN);
- if( null != _sms ) {
- throw new RuntimeException("ScreenModeStatus "+_sms+" already mapped to "+screenFQN);
- }
- screenFQN2ScreenModeStatus.put(screenFQN, sms);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.map "+screenFQN+" -> "+sms);
- }
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
-
- /**
- * @param screen the prev user
- * @return true if mapping is empty, ie no more usage of the mapped ScreenModeStatus
- */
- protected static void unmapScreenModeStatus(String screenFQN) {
- screen2ScreenModeStatusLock.lock();
- try {
- unmapScreenModeStatusUnlocked(screenFQN);
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
- protected static void unmapScreenModeStatusUnlocked(String screenFQN) {
- ScreenModeStatus sms = screenFQN2ScreenModeStatus.remove(screenFQN);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.unmap "+screenFQN+" -> "+sms);
- }
- }
-
- protected static ScreenModeStatus getScreenModeStatus(String screenFQN) {
- screen2ScreenModeStatusLock.lock();
- try {
- return getScreenModeStatusUnlocked(screenFQN);
- } finally {
- screen2ScreenModeStatusLock.unlock();
- }
- }
- protected static ScreenModeStatus getScreenModeStatusUnlocked(String screenFQN) {
- return screenFQN2ScreenModeStatus.get(screenFQN);
- }
-
- protected static void lockScreenModeStatus() {
- screen2ScreenModeStatusLock.lock();
- }
-
- protected static void unlockScreenModeStatus() {
- screen2ScreenModeStatusLock.unlock();
- }
-
- public ScreenModeStatus(ArrayHashSet<ScreenMode> screenModes,
- IntIntHashMap screenModesIdx2NativeIdx) {
- this.screenModes = screenModes;
- this.screenModesIdx2NativeIdx = screenModesIdx2NativeIdx;
- this.screenModeChangedByOwner = false;
- }
-
- protected final void setOriginalScreenMode(ScreenMode originalScreenMode) {
- this.originalScreenMode = originalScreenMode;
- this.currentScreenMode = originalScreenMode;
- }
-
- public final ScreenMode getOriginalScreenMode() {
- return originalScreenMode;
- }
-
- public final ScreenMode getCurrentScreenMode() {
- lock();
- try {
- return currentScreenMode;
- } finally {
- unlock();
- }
- }
-
- /**
- * We cannot guarantee that we won't interfere w/ another running
- * application's screen mode change.
- * <p>
- * At least we only return <code>true</true> if the owner, ie. the Screen,
- * has changed the screen mode and if the original screen mode
- * is not current the current one.
- * </p>
- * @return
- */
- public final boolean isOriginalModeChangedByOwner() {
- lock();
- try {
- return screenModeChangedByOwner && !isCurrentModeOriginalMode();
- } finally {
- unlock();
- }
- }
-
- protected final boolean isCurrentModeOriginalMode() {
- if(null != currentScreenMode && null != originalScreenMode) {
- return currentScreenMode.hashCode() == originalScreenMode.hashCode();
- }
- return true;
- }
-
- protected final ArrayHashSet<ScreenMode> getScreenModes() {
- return screenModes;
- }
-
- protected final IntIntHashMap getScreenModesIdx2NativeIdx() {
- return screenModesIdx2NativeIdx;
- }
-
- protected final int addListener(ScreenModeListener l) {
- lock();
- try {
- listener.add(l);
- if(DEBUG) {
- System.err.println("ScreenModeStatus.addListener (size: "+listener.size()+"): "+l);
- }
- return listener.size();
- } finally {
- unlock();
- }
- }
-
- protected final int removeListener(ScreenModeListener l) {
- lock();
- try {
- if(!listener.remove(l)) {
- throw new RuntimeException("ScreenModeListener "+l+" not contained");
- }
- if(DEBUG) {
- System.err.println("ScreenModeStatus.removeListener (size: "+listener.size()+"): "+l);
- }
- return listener.size();
- } finally {
- unlock();
- }
- }
-
- protected final void fireScreenModeChangeNotify(ScreenMode desiredScreenMode) {
- lock();
- try {
- for(int i=0; i<listener.size(); i++) {
- listener.get(i).screenModeChangeNotify(desiredScreenMode);
- }
- } finally {
- unlock();
- }
- }
-
- protected void fireScreenModeChanged(ScreenMode currentScreenMode, boolean success) {
- lock();
- try {
- if(success) {
- this.currentScreenMode = currentScreenMode;
- this.screenModeChangedByOwner = !isCurrentModeOriginalMode();
- }
- for(int i=0; i<listener.size(); i++) {
- listener.get(i).screenModeChanged(currentScreenMode, success);
- }
- } finally {
- unlock();
- }
- }
-
- protected final void lock() throws RuntimeException {
- lock.lock();
- }
-
- protected final void unlock() throws RuntimeException {
- lock.unlock();
- }
-}
diff --git a/src/newt/classes/jogamp/newt/ScreenMonitorState.java b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
new file mode 100644
index 000000000..01e6cfee9
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/ScreenMonitorState.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright 2010 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;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.Screen;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ScreenMonitorState {
+ private static boolean DEBUG = Screen.DEBUG;
+
+ private final RecursiveLock lock = LockFactory.createRecursiveLock();
+ private final ArrayHashSet<MonitorDevice> allMonitors;
+ private final ArrayHashSet<MonitorMode> allMonitorModes;
+ private ArrayList<MonitorModeListener> listener = new ArrayList<MonitorModeListener>();
+
+ private static HashMap<String, ScreenMonitorState> screenFQN2ScreenMonitorState = new HashMap<String, ScreenMonitorState>();
+ private static RecursiveLock screen2ScreenMonitorState = LockFactory.createRecursiveLock();
+
+ protected static void mapScreenMonitorState(String screenFQN, ScreenMonitorState sms) {
+ screen2ScreenMonitorState.lock();
+ try {
+ ScreenMonitorState _sms = screenFQN2ScreenMonitorState.get(screenFQN);
+ if( null != _sms ) {
+ throw new RuntimeException("ScreenMonitorState "+_sms+" already mapped to "+screenFQN);
+ }
+ screenFQN2ScreenMonitorState.put(screenFQN, sms);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.map "+screenFQN+" -> "+sms);
+ }
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+
+ /**
+ * @param screen the prev user
+ * @return true if mapping is empty, ie no more usage of the mapped ScreenMonitorState
+ */
+ protected static void unmapScreenMonitorState(String screenFQN) {
+ screen2ScreenMonitorState.lock();
+ try {
+ unmapScreenMonitorStateUnlocked(screenFQN);
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+ protected static void unmapScreenMonitorStateUnlocked(String screenFQN) {
+ ScreenMonitorState sms = screenFQN2ScreenMonitorState.remove(screenFQN);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.unmap "+screenFQN+" -> "+sms);
+ }
+ }
+
+ protected static ScreenMonitorState getScreenMonitorState(String screenFQN) {
+ screen2ScreenMonitorState.lock();
+ try {
+ return getScreenMonitorStateUnlocked(screenFQN);
+ } finally {
+ screen2ScreenMonitorState.unlock();
+ }
+ }
+ protected static ScreenMonitorState getScreenMonitorStateUnlocked(String screenFQN) {
+ return screenFQN2ScreenMonitorState.get(screenFQN);
+ }
+
+ protected static void lockScreenMonitorState() {
+ screen2ScreenMonitorState.lock();
+ }
+
+ protected static void unlockScreenMonitorState() {
+ screen2ScreenMonitorState.unlock();
+ }
+
+ public ScreenMonitorState(ArrayHashSet<MonitorDevice> allMonitors,
+ ArrayHashSet<MonitorMode> allMonitorModes) {
+ this.allMonitors = allMonitors;
+ this.allMonitorModes = allMonitorModes;
+ }
+
+ protected ArrayHashSet<MonitorDevice> getMonitorDevices() {
+ return allMonitors;
+ }
+
+ protected ArrayHashSet<MonitorMode> getMonitorModes() {
+ return allMonitorModes;
+ }
+
+ protected final int addListener(MonitorModeListener l) {
+ lock();
+ try {
+ listener.add(l);
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.addListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final int removeListener(MonitorModeListener l) {
+ lock();
+ try {
+ if(!listener.remove(l)) {
+ throw new RuntimeException("MonitorModeListener "+l+" not contained");
+ }
+ if(DEBUG) {
+ System.err.println("ScreenMonitorState.removeListener (size: "+listener.size()+"): "+l);
+ }
+ return listener.size();
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final MonitorDevice getMonitor(MonitorDevice monitor) {
+ return allMonitors.get(monitor);
+ }
+
+ protected final void validateMonitor(MonitorDevice monitor) {
+ final MonitorDevice md = allMonitors.get(monitor);
+ if( null == md ) {
+ throw new InternalError("Monitor unknown: "+monitor);
+ }
+ }
+
+ protected final void fireMonitorModeChangeNotify(MonitorDevice monitor, MonitorMode desiredMode) {
+ lock();
+ try {
+ validateMonitor(monitor);
+ final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGE_NOTIFY, monitor, System.currentTimeMillis(), desiredMode);
+ for(int i=0; i<listener.size(); i++) {
+ listener.get(i).monitorModeChangeNotify(me);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected void fireMonitorModeChanged(MonitorDevice monitor, MonitorMode currentMode, boolean success) {
+ lock();
+ try {
+ validateMonitor(monitor);
+ final MonitorEvent me = new MonitorEvent(MonitorEvent.EVENT_MONITOR_MODE_CHANGED, monitor, System.currentTimeMillis(), currentMode);
+ for(int i=0; i<listener.size(); i++) {
+ listener.get(i).monitorModeChanged(me, success);
+ }
+ } finally {
+ unlock();
+ }
+ }
+
+ protected final void lock() throws RuntimeException {
+ lock.lock();
+ }
+
+ protected final void unlock() throws RuntimeException {
+ lock.unlock();
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 074f635e4..7f7cb61a9 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,33 +29,15 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt;
-import java.util.ArrayList;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
-
-import com.jogamp.common.util.ReflectionUtil;
-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.ScreenMode;
-import com.jogamp.newt.event.InputEvent;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.KeyListener;
-import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.event.MouseListener;
-import com.jogamp.newt.event.NEWTEvent;
-import com.jogamp.newt.event.NEWTEventConsumer;
-import com.jogamp.newt.event.ScreenModeListener;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.event.WindowListener;
-import com.jogamp.newt.event.WindowUpdateEvent;
+import java.util.ArrayList;
+import java.util.List;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -65,28 +47,115 @@ 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.PixelRectangle;
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.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.Screen;
+import com.jogamp.newt.Window;
+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.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+
public abstract class WindowImpl implements Window, NEWTEventConsumer
{
- public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
-
+ public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
+
+ ScreenImpl.initSingleton();
+ }
+
+ protected static final ArrayList<WeakReference<WindowImpl>> windowList = new ArrayList<WeakReference<WindowImpl>>();
+
+ /** Maybe utilized at a shutdown hook, impl. does not block. */
+ public static final void shutdownAll() {
+ final int wCount = windowList.size();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.shutdownAll "+wCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<wCount && windowList.size()>0; i++) { // be safe ..
+ final WindowImpl w = windowList.remove(0).get();
+ if(DEBUG_IMPLEMENTATION) {
+ final long wh = null != w ? w.getWindowHandle() : 0;
+ System.err.println("Window.shutdownAll["+(i+1)+"/"+wCount+"]: "+toHexString(wh)+", GCed "+(null==w));
+ }
+ if( null != w ) {
+ w.shutdown();
+ }
+ }
+ }
+ private static void addWindow2List(WindowImpl window) {
+ synchronized(windowList) {
+ // GC before add
+ int i=0, gced=0;
+ while( i < windowList.size() ) {
+ if( null == windowList.get(i).get() ) {
+ gced++;
+ windowList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ windowList.add(new WeakReference<WindowImpl>(window));
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.addWindow2List: GCed "+gced+", size "+windowList.size());
+ }
+ }
+ }
+
/** Timeout of queued events (repaint and resize) */
- static final long QUEUED_EVENT_TO = 1200; // ms
-
+ static final long QUEUED_EVENT_TO = 1200; // ms
+
+ private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
+
+ //
+ // Volatile: Multithread Mutable Access
+ //
private volatile long windowHandle = 0; // lifecycle critical
private volatile boolean visible = false; // lifecycle critical
- private RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock
- private RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); // Surface only lock
-
+ private volatile boolean hasFocus = false;
+ private volatile int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
+ private volatile int x = 64, y = 64; // client-area pos w/o insets
+ private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
+ private boolean blockInsetsChange = false; // block insets change (from same thread)
+
+ private final RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock
+ private int surfaceLockCount = 0; // surface lock recursion count
+
private ScreenImpl screen; // never null after create - may change reference though (reparent)
private boolean screenReferenceAdded = false;
private NativeWindow parentWindow = null;
@@ -94,56 +163,102 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private AbstractGraphicsConfiguration config = null; // control access due to delegation
protected CapabilitiesImmutable capsRequested = null;
protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default
- private boolean fullscreen = false, hasFocus = false, brokenFocusChange = false;
- private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user
- private int x = 64, y = 64; // client-area pos w/o insets
+ private boolean fullscreen = false, brokenFocusChange = false;
+ private List<MonitorDevice> fullscreenMonitors = null;
+ private boolean fullscreenUseMainMonitor = true;
private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user)
- private Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
-
+
private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
+ 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 boolean undecorated = false;
private boolean alwaysOnTop = false;
+ private PointerIconImpl pointerIcon = null;
private boolean pointerVisible = true;
private boolean pointerConfined = false;
private LifecycleHook lifecycleHook = null;
- private boolean handleDestroyNotify = true;
+ private Runnable windowDestroyNotifyAction = null;
private FocusRunnable focusAction = null;
private KeyListener keyboardFocusHandler = null;
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
-
- private Object childWindowsLock = new Object();
- private ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>();
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+
+ private final Object childWindowsLock = new Object();
+ private final ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>();
private ArrayList<MouseListener> mouseListeners = new ArrayList<MouseListener>();
- private int mouseButtonPressed = 0; // current pressed mouse button number
- private long lastMousePressed = 0; // last time when a mouse button was pressed
- private int lastMouseClickCount = 0; // last mouse button click count
- private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic)
- private Point lastMousePosition = new Point();
- private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>();
+ /** from event passing: {@link WindowImpl#consumePointerEvent(MouseEvent)}. */
+ private static class PointerState0 {
+ /** Pointer entered window - is inside the window (may be synthetic) */
+ boolean insideWindow = false;
+ /** Mouse EXIT has been sent (only for MOUSE type enter/exit)*/
+ boolean exitSent = false;
- private ArrayList<WindowListener> windowListeners = new ArrayList<WindowListener>();
- private boolean repaintQueued = false;
+ /** last time when a pointer button was pressed */
+ long lastButtonPressTime = 0;
- // Workaround for initialization order problems on Mac OS X
- // between native Newt and (apparently) Fmod -- if Fmod is
- // initialized first then the connection to the window server
- // breaks, leading to errors from deep within the AppKit
- public static void init(String type) {
- if (NativeWindowFactory.TYPE_MACOSX.equals(type)) {
- try {
- getWindowClass(type);
- } catch (Exception e) {
- e.printStackTrace();
+ /** Pointer in dragging mode */
+ boolean dragging = false;
+
+ void clearButton() {
+ lastButtonPressTime = 0;
+ }
+ public String toString() { return "PState0[inside "+insideWindow+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+", dragging "+dragging+"]"; }
+ }
+ private final PointerState0 pState0 = new PointerState0();
+
+ /** from direct input: {@link WindowImpl#doPointerEvent(boolean, boolean, int[], short, int, int, boolean, short[], int[], int[], float[], float, float[], float)}. */
+ private static class PointerState1 extends PointerState0 {
+ /** Current pressed mouse button number */
+ short buttonPressed = (short)0;
+ /** Current pressed mouse button modifier mask */
+ int buttonPressedMask = 0;
+ /** Last mouse button click count */
+ short lastButtonClickCount = (short)0;
+
+ @Override
+ final void clearButton() {
+ super.clearButton();
+ lastButtonClickCount = (short)0;
+ if( !dragging || 0 == buttonPressedMask ) {
+ buttonPressed = 0;
+ buttonPressedMask = 0;
+ dragging = false;
+ }
+ }
+
+ /** Last pointer-move position for 8 touch-down pointers */
+ final Point[] movePositions = new Point[] {
+ new Point(), new Point(), new Point(), new Point(),
+ new Point(), new Point(), new Point(), new Point() };
+ final Point getMovePosition(int id) {
+ if( 0 <= id && id < movePositions.length ) {
+ return movePositions[id];
}
+ return null;
}
+ public final String toString() { return "PState1[inside "+insideWindow+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+
+ ", pressed [button "+buttonPressed+", mask "+buttonPressedMask+", dragging "+dragging+", clickCount "+lastButtonClickCount+"]"; }
}
+ private final PointerState1 pState1 = new PointerState1();
+
+ /** Pointer names -> pointer ID (consecutive index, starting w/ 0) */
+ private final ArrayHashSet<Integer> pName2pID = new ArrayHashSet<Integer>();
+
+ private boolean defaultGestureHandlerEnabled = true;
+ private DoubleTapScrollGesture gesture2PtrTouchScroll = null;
+ private ArrayList<GestureHandler> pointerGestureHandler = new ArrayList<GestureHandler>();
+
+ private ArrayList<GestureHandler.GestureListener> gestureListeners = new ArrayList<GestureHandler.GestureListener>();
+
+ private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>();
+
+ private ArrayList<WindowListener> windowListeners = new ArrayList<WindowListener>();
+ private boolean repaintQueued = false;
//
// Construction Methods
@@ -152,26 +267,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private static Class<?> getWindowClass(String type)
throws ClassNotFoundException
{
- Class<?> windowClass = NewtFactory.getCustomClass(type, "Window");
- if(null==windowClass) {
- if (NativeWindowFactory.TYPE_ANDROID == type) {
- windowClass = Class.forName("jogamp.newt.driver.android.AndroidWindow");
- } else if (NativeWindowFactory.TYPE_EGL == type) {
- windowClass = Class.forName("jogamp.newt.driver.kd.KDWindow");
- } else if (NativeWindowFactory.TYPE_WINDOWS == type) {
- windowClass = Class.forName("jogamp.newt.driver.windows.WindowsWindow");
- } else if (NativeWindowFactory.TYPE_MACOSX == type) {
- windowClass = Class.forName("jogamp.newt.driver.macosx.MacWindow");
- } else if (NativeWindowFactory.TYPE_X11 == type) {
- windowClass = Class.forName("jogamp.newt.driver.x11.X11Window");
- } else if (NativeWindowFactory.TYPE_AWT == type) {
- windowClass = Class.forName("jogamp.newt.driver.awt.AWTWindow");
- } else {
- throw new NativeWindowException("Unknown window type \"" + type + "\"");
- }
- }
+ final Class<?> windowClass = NewtFactory.getCustomClass(type, "WindowDriver");
if(null==windowClass) {
- throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".Window>");
+ throw new ClassNotFoundException("Failed to find NEWT Window Class <"+type+".WindowDriver>");
}
return windowClass;
}
@@ -189,15 +287,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
window.parentWindowHandle = parentWindowHandle;
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
- window.setUndecorated(0!=parentWindowHandle);
window.instantiationFinished();
+ addWindow2List(window);
return window;
} catch (Throwable t) {
t.printStackTrace();
throw new NativeWindowException(t);
}
}
-
+
public static WindowImpl create(Object[] cstrArguments, Screen screen, CapabilitiesImmutable caps) {
try {
Class<?> windowClass = getWindowClass(screen.getDisplay().getType());
@@ -212,16 +310,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
+ window.instantiationFinished();
+ addWindow2List(window);
return window;
} catch (Throwable t) {
throw new NativeWindowException(t);
}
}
+ /** Fast invalidation of instance w/o any blocking function call. */
+ private final void shutdown() {
+ if(null!=lifecycleHook) {
+ lifecycleHook.shutdownRenderingAction();
+ }
+ setWindowHandle(0);
+ visible = false;
+ fullscreen = false;
+ fullscreenMonitors = null;
+ fullscreenUseMainMonitor = true;
+ hasFocus = false;
+ parentWindowHandle = 0;
+ }
+
protected final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
config = cfg;
}
-
+
public static interface LifecycleHook {
/**
* Reset of internal state counter, ie totalFrames, etc.
@@ -229,15 +343,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
*/
public abstract void resetCounter();
- /**
- * Invoked after Window setVisible,
+ /**
+ * Invoked after Window setVisible,
* allows allocating resources depending on the native Window.
* Called from EDT while window is locked.
*/
void setVisibleActionPost(boolean visible, boolean nativeWindowCreated);
- /**
- * Invoked before Window destroy action,
+ /**
+ * Notifies the receiver to preserve resources (GL, ..)
+ * for the next destroy*() calls (only), if supported and if <code>value</code> is <code>true</code>, otherwise clears preservation flag.
+ * @param value <code>true</code> to set the one-shot preservation if supported, otherwise clears it.
+ */
+ void preserveGLStateAtDestroy(boolean value);
+
+ /**
+ * Invoked before Window destroy action,
* allows releasing of resources depending on the native Window.<br>
* Surface not locked yet.<br>
* Called not necessarily from EDT.
@@ -253,7 +374,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
void destroyActionInLock();
/**
- * Invoked for expensive modifications, ie while reparenting and ScreenMode change.<br>
+ * Invoked for expensive modifications, ie while reparenting and MonitorMode change.<br>
* No lock is hold when invoked.<br>
*
* @return true is paused, otherwise false. If true {@link #resumeRenderingAction()} shall be issued.
@@ -263,12 +384,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
boolean pauseRenderingAction();
/**
- * Invoked for expensive modifications, ie while reparenting and ScreenMode change.
+ * Invoked for expensive modifications, ie while reparenting and MonitorMode change.
* No lock is hold when invoked.<br>
*
* @see #pauseRenderingAction()
*/
void resumeRenderingAction();
+
+ /**
+ * Shutdown rendering action (thread) abnormally.
+ * <p>
+ * Should be called only at shutdown, if necessary.
+ * </p>
+ */
+ void shutdownRenderingAction();
}
private boolean createNative() {
@@ -279,37 +408,59 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
} else {
tStart = 0;
}
-
- if( null != parentWindow &&
+
+ if( null != parentWindow &&
NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindow.lockSurface() ) {
throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow);
}
-
+
+ final boolean hasParent = null != parentWindow || 0 != this.parentWindowHandle;
+
// child window: position defaults to 0/0, no auto position, no negative position
- if( null != parentWindow && ( autoPosition || 0>getX() || 0>getY() ) ) {
+ if( hasParent && ( autoPosition || 0>getX() || 0>getY() ) ) {
definePosition(0, 0);
}
boolean postParentlockFocus = false;
try {
if(validateParentWindowHandle()) {
- if(screenReferenceAdded) {
- throw new InternalError("XXX");
- }
- if(canCreateNativeImpl()) {
+ if( !screenReferenceAdded ) {
screen.addReference();
screenReferenceAdded = true;
+ }
+ if(canCreateNativeImpl()) {
+ final int wX, wY;
+ final boolean usePosition;
+ if( autoPosition ) {
+ wX = 0;
+ wY = 0;
+ usePosition = false;
+ } else {
+ wX = getX();
+ wY = getY();
+ usePosition = true;
+ }
+ final long t0 = System.currentTimeMillis();
createNativeImpl();
- screen.addScreenModeListener(screenModeListenerImpl);
+ screen.addMonitorModeListener(monitorModeListenerImpl);
setTitleImpl(title);
- setPointerVisibleImpl(pointerVisible);
+ setPointerIconIntern(pointerIcon);
+ setPointerVisibleIntern(pointerVisible);
confinePointerImpl(pointerConfined);
- if(waitForVisible(true, false)) {
+ setKeyboardVisible(keyboardVisible);
+ final long remainingV = waitForVisible(true, false);
+ if( 0 <= remainingV ) {
if(isFullscreen()) {
synchronized(fullScreenAction) {
fullscreen = false; // trigger a state change
fullScreenAction.init(true);
fullScreenAction.run();
}
+ } else if ( !hasParent ) {
+ // Wait until position is reached within tolerances, either auto-position or custom position.
+ waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW);
+ }
+ if (DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.createNative(): elapsed "+(System.currentTimeMillis()-t0)+" ms");
}
postParentlockFocus = true;
}
@@ -322,7 +473,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
if(postParentlockFocus) {
// harmonize focus behavior for all platforms: focus on creation
- requestFocusInt(isFullscreen() /* skipFocusAction */);
+ requestFocusInt(isFullscreen() /* skipFocusAction if fullscreen */);
((DisplayImpl) screen.getDisplay()).dispatchMessagesNative(); // status up2date
}
if(DEBUG_IMPLEMENTATION) {
@@ -387,16 +538,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//----------------------------------------------------------------------
// WindowClosingProtocol implementation
//
- private Object closingListenerLock = new Object();
+ private final Object closingListenerLock = new Object();
private WindowClosingMode defaultCloseOperation = WindowClosingMode.DISPOSE_ON_CLOSE;
- public WindowClosingMode getDefaultCloseOperation() {
+ @Override
+ public final WindowClosingMode getDefaultCloseOperation() {
synchronized (closingListenerLock) {
return defaultCloseOperation;
}
}
- public WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
+ @Override
+ public final WindowClosingMode setDefaultCloseOperation(WindowClosingMode op) {
synchronized (closingListenerLock) {
WindowClosingMode _op = defaultCloseOperation;
defaultCloseOperation = op;
@@ -410,28 +563,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
/**
* Notifies the driver impl. that the instantiation is finished,
- * ie. instance created and all fields set.
+ * ie. instance created and all fields set.
*/
protected void instantiationFinished() {
// nop
}
-
+
protected boolean canCreateNativeImpl() {
return true; // default: always able to be created
}
-
- /**
+
+ /**
* The native implementation must set the native windowHandle.<br>
*
* <p>
* The implementation shall respect the states {@link #isAlwaysOnTop()}/{@link #FLAG_IS_ALWAYSONTOP} and
* {@link #isUndecorated()}/{@link #FLAG_IS_UNDECORATED}, ie. the created window shall reflect those settings.
* </p>
- *
+ *
* <p>
* The implementation should invoke the referenced java state callbacks
* to notify this Java object of state changes.</p>
- *
+ *
* @see #windowDestroyNotify(boolean)
* @see #focusChanged(boolean, boolean)
* @see #visibleChanged(boolean, boolean)
@@ -443,11 +596,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected abstract void closeNativeImpl();
- /**
- * The native implementation must invoke {@link #focusChanged(boolean, boolean)}
- * to change the focus state, if <code>force == false</code>.
- * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}.
- *
+ /**
+ * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
+ * <p>
+ * If if <code>force == false</code> the native implementation
+ * may only request focus if not yet owner.</p>
+ * <p>
+ * {@link #focusChanged(boolean, boolean)} should be called
+ * to notify about the focus traversal.
+ * </p>
+ *
* @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request
*/
protected abstract void requestFocusImpl(boolean force);
@@ -457,22 +615,23 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
public static final int FLAG_CHANGE_FULLSCREEN = 1 << 2;
public static final int FLAG_CHANGE_ALWAYSONTOP = 1 << 3;
public static final int FLAG_CHANGE_VISIBILITY = 1 << 4;
-
+
public static final int FLAG_HAS_PARENT = 1 << 8;
public static final int FLAG_IS_UNDECORATED = 1 << 9;
public static final int FLAG_IS_FULLSCREEN = 1 << 10;
- public static final int FLAG_IS_ALWAYSONTOP = 1 << 11;
- public static final int FLAG_IS_VISIBLE = 1 << 12;
+ public static final int FLAG_IS_FULLSCREEN_SPAN = 1 << 11;
+ public static final int FLAG_IS_ALWAYSONTOP = 1 << 12;
+ public static final int FLAG_IS_VISIBLE = 1 << 13;
/**
* The native implementation should invoke the referenced java state callbacks
* to notify this Java object of state changes.
- *
+ *
* <p>
* Implementations shall set x/y to 0, in case it's negative. This could happen due
* to insets and positioning a decorated window to 0/0, which would place the frame
* outside of the screen.</p>
- *
+ *
* @param x client-area position, or <0 if unchanged
* @param y client-area position, or <0 if unchanged
* @param width client-area size, or <=0 if unchanged
@@ -484,6 +643,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
*/
protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags);
+ /**
+ * Tests whether a single reconfigure flag is supported by implementation.
+ * <p>
+ * Default is all but {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ */
+ protected boolean isReconfigureFlagSupported(int changeFlags) {
+ return 0 == ( changeFlags & FLAG_IS_FULLSCREEN_SPAN );
+ }
+
protected int getReconfigureFlags(int changeFlags, boolean visible) {
return changeFlags |= ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) |
( isUndecorated() ? FLAG_IS_UNDECORATED : 0 ) |
@@ -494,60 +663,68 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
protected static String getReconfigureFlagsAsString(StringBuilder sb, int flags) {
if(null == sb) { sb = new StringBuilder(); }
sb.append("[");
-
+
if( 0 != ( FLAG_CHANGE_PARENTING & flags) ) {
sb.append("*");
}
- sb.append("PARENT_");
+ sb.append("PARENT ");
sb.append(0 != ( FLAG_HAS_PARENT & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
sb.append("*");
}
- sb.append("FS_");
+ sb.append("FS ");
sb.append(0 != ( FLAG_IS_FULLSCREEN & flags));
- sb.append(", ");
+ sb.append("[span ");
+ sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags));
+ sb.append("], ");
if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) {
sb.append("*");
}
- sb.append("UNDECOR_");
+ sb.append("UNDECOR ");
sb.append(0 != ( FLAG_IS_UNDECORATED & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_ALWAYSONTOP & flags) ) {
sb.append("*");
}
- sb.append("ALWAYSONTOP_");
+ sb.append("ALWAYSONTOP ");
sb.append(0 != ( FLAG_IS_ALWAYSONTOP & flags));
sb.append(", ");
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
sb.append("*");
}
- sb.append("VISIBLE_");
+ sb.append("VISIBLE ");
sb.append(0 != ( FLAG_IS_VISIBLE & flags));
-
+
sb.append("]");
return sb.toString();
}
-
+
protected void setTitleImpl(String title) {}
/**
- * Return screen coordinates of the given coordinates
- * or null, in which case a NativeWindow traversal shall being used
+ * Translates the given window client-area coordinates with top-left origin
+ * to screen coordinates.
+ * <p>
+ * Since the position reflects the client area, it does not include the insets.
+ * </p>
+ * <p>
+ * May return <code>null</code>, in which case the caller shall traverse through the NativeWindow tree
* as demonstrated in {@link #getLocationOnScreen(javax.media.nativewindow.util.Point)}.
+ * </p>
*
* @return if not null, the screen location of the given coordinates
*/
protected abstract Point getLocationOnScreenImpl(int x, int y);
-
+
/** Triggered by user via {@link #getInsets()}.<br>
- * Implementations may implement this hook to update the insets.<br>
+ * Implementations may implement this hook to update the insets.<br>
* However, they may prefer the event driven path via {@link #insetsChanged(boolean, int, int, int, int)}.
- *
+ *
* @see #getInsets()
* @see #insetsChanged(boolean, int, int, int, int)
*/
@@ -556,15 +733,18 @@ 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
//
- public final int lockSurface() {
- windowLock.lock();
- surfaceLock.lock();
- int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+ @Override
+ public final int lockSurface() throws NativeWindowException, RuntimeException {
+ final RecursiveLock _wlock = windowLock;
+ _wlock.lock();
+ surfaceLockCount++;
+ int res = ( 1 == surfaceLockCount ) ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
if ( LOCK_SURFACE_NOT_READY == res ) {
try {
@@ -581,19 +761,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
} finally {
if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- windowLock.unlock();
+ surfaceLockCount--;
+ _wlock.unlock();
}
}
}
return res;
}
+ @Override
public final void unlockSurface() {
- surfaceLock.validateLocked();
- windowLock.validateLocked();
+ final RecursiveLock _wlock = windowLock;
+ _wlock.validateLocked();
- if (surfaceLock.getHoldCount() == 1) {
+ if ( 1 == surfaceLockCount ) {
final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
try {
unlockSurfaceImpl();
@@ -601,52 +782,67 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
adevice.unlock();
}
}
- surfaceLock.unlock();
- windowLock.unlock();
+ surfaceLockCount--;
+ _wlock.unlock();
}
- public final boolean isWindowLockedByOtherThread() {
+ @Override
+ public final boolean isSurfaceLockedByOtherThread() {
return windowLock.isLockedByOtherThread();
}
- public final boolean isWindowLocked() {
- return windowLock.isLocked();
+ @Override
+ public final Thread getSurfaceLockOwner() {
+ return windowLock.getOwner();
}
- public final Thread getWindowLockOwner() {
- return windowLock.getOwner();
+ public final RecursiveLock getLock() {
+ return windowLock;
}
- public final boolean isSurfaceLockedByOtherThread() {
- return surfaceLock.isLockedByOtherThread();
+ @Override
+ public long getSurfaceHandle() {
+ return windowHandle; // default: return window handle
}
- public final boolean isSurfaceLocked() {
- return surfaceLock.isLocked();
+ @Override
+ public boolean surfaceSwap() {
+ return false;
}
- public final Thread getSurfaceLockOwner() {
- return surfaceLock.getOwner();
+ @Override
+ public final void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
}
- public long getSurfaceHandle() {
- return windowHandle; // default: return window handle
+ @Override
+ public final void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
}
- public boolean surfaceSwap() {
- return false;
+ @Override
+ public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public final void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
}
+ @Override
public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
return config.getNativeGraphicsConfiguration();
}
+ @Override
public final long getDisplayHandle() {
- return getScreen().getDisplay().getHandle();
+ return config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
}
+ @Override
public final int getScreenIndex() {
- return getScreen().getIndex();
+ return screen.getIndex();
}
//----------------------------------------------------------------------
@@ -655,22 +851,26 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// public final void destroy() - see below
+ @Override
public final NativeWindow getParent() {
return parentWindow;
}
+ @Override
public final long getWindowHandle() {
return windowHandle;
}
+ @Override
public Point getLocationOnScreen(Point storage) {
if(isNativeValid()) {
Point d;
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
d = getLocationOnScreenImpl(0, 0);
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
if(null!=d) {
if(null!=storage) {
@@ -698,27 +898,31 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Window
//
+ @Override
public final boolean isNativeValid() {
return 0 != windowHandle ;
}
+ @Override
public final Screen getScreen() {
return screen;
}
+ @Override
+ public final MonitorDevice getMainMonitor() {
+ return screen.getMainMonitor(new Rectangle(getX(), getY(), getWidth(), getHeight()));
+ }
+
protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) {
- reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));
- }
+ reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));
+ }
final void setVisibleActionImpl(boolean visible) {
boolean nativeWindowCreated = false;
boolean madeVisible = false;
-
- windowLock.lock();
- try {
- if(null!=lifecycleHook) {
- lifecycleHook.resetCounter();
- }
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
+ try {
if(!visible && null!=childWindows && childWindows.size()>0) {
synchronized(childWindowsLock) {
for(int i = 0; i < childWindows.size(); i++ ) {
@@ -735,12 +939,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
madeVisible = nativeWindowCreated;
}
// always flag visible, allowing a retry ..
- WindowImpl.this.visible = true;
+ WindowImpl.this.visible = true;
} else if(WindowImpl.this.visible != visible) {
if(isNativeValid()) {
setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight());
- WindowImpl.this.waitForVisible(visible, true);
+ WindowImpl.this.waitForVisible(visible, false);
madeVisible = visible;
+ } else {
+ WindowImpl.this.visible = true;
}
}
@@ -762,7 +968,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible);
}
} finally {
- windowLock.unlock();
+ if(null!=lifecycleHook) {
+ lifecycleHook.resetCounter();
+ }
+ _lock.unlock();
}
if( nativeWindowCreated || madeVisible ) {
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
@@ -775,54 +984,58 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.visible = visible;
}
+ @Override
public final void run() {
setVisibleActionImpl(visible);
}
}
- public void setVisible(boolean visible) {
+ @Override
+ public final void setVisible(boolean wait, boolean visible) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow));
}
- runOnEDTIfAvail(true, new VisibleAction(visible));
+ runOnEDTIfAvail(wait, new VisibleAction(visible));
}
-
+
+ @Override
+ public final void setVisible(boolean visible) {
+ setVisible(true, visible);
+ }
+
private class SetSizeAction implements Runnable {
int width, height;
+ boolean disregardFS;
- private SetSizeAction(int w, int h) {
+ private SetSizeAction(int w, int h, boolean disregardFS) {
this.width = w;
this.height = h;
+ this.disregardFS = disregardFS;
}
+ @Override
public final void run() {
- boolean recreate = false;
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
- if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) {
- recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ if ( ( disregardFS || !isFullscreen() ) && ( getWidth() != width || getHeight() != height ) ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate);
- }
- if(recreate) {
- // will trigger visibleAction:=2 -> create if wasVisible
- final boolean wasVisible = WindowImpl.this.visible;
- screen.addReference(); // retain screen
- destroyAction.run();
- WindowImpl.this.visible = wasVisible;
+ System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
}
int visibleAction; // 0 nop, 1 invisible, 2 visible (create)
- if ( isNativeValid() && 0>=width*height && visible ) {
+ if ( visible && isNativeValid() && ( 0 >= width || 0 >= height ) ) {
visibleAction=1; // invisible
defineSize(0, 0);
- } else if ( !isNativeValid() && 0<width*height && visible ) {
+ } else if ( visible && !isNativeValid() && 0 < width && 0 < height ) {
visibleAction = 2; // visible (create)
defineSize(width, height);
- } else if ( isNativeValid() ) {
+ } else if ( visible && isNativeValid() ) {
visibleAction = 0;
// this width/height will be set by windowChanged, called by the native implementation
reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureFlags(0, isVisible()));
+ WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
} else {
+ // invisible or invalid w/ 0 size
visibleAction = 0;
defineSize(width, height);
}
@@ -835,22 +1048,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- if(recreate) {
- screen.removeReference(); // bring back ref-count
- }
- windowLock.unlock();
+ _lock.unlock();
}
}
}
- public void setSize(int width, int height) {
- runOnEDTIfAvail(true, new SetSizeAction(width, height));
- }
- public void setTopLevelSize(int width, int height) {
+ private void setFullscreenSize(int width, int height) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, true));
+ }
+ @Override
+ public final void setSize(int width, int height) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, false));
+ }
+ @Override
+ public final void setTopLevelSize(int width, int height) {
setSize(width - getInsets().getTotalWidth(), height - getInsets().getTotalHeight());
}
private class DestroyAction implements Runnable {
+ @Override
public final void run() {
boolean animatorPaused = false;
if(null!=lifecycleHook) {
@@ -859,11 +1075,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=lifecycleHook) {
lifecycleHook.destroyActionPreLock();
}
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window DestroyAction() "+getThreadName());
+ System.err.println("Window DestroyAction() hasScreen "+(null != screen)+", isNativeValid "+isNativeValid()+" - "+getThreadName());
}
+
+ // send synced destroy-notify notification
+ sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+
// Childs first ..
synchronized(childWindowsLock) {
if(childWindows.size()>0) {
@@ -873,8 +1094,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
while( clonedChildWindows.size() > 0 ) {
NativeWindow nw = clonedChildWindows.remove(0);
if(nw instanceof WindowImpl) {
- ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- ((WindowImpl)nw).destroy();
+ ((WindowImpl)nw).windowDestroyNotify(true);
} else {
nw.destroy();
}
@@ -887,16 +1107,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
lifecycleHook.destroyActionInLock();
}
- if( null != screen ) {
- if( isNativeValid() ) {
- screen.removeScreenModeListener(screenModeListenerImpl);
- closeNativeImpl();
- removeScreenReference();
- }
- Display dpy = screen.getDisplay();
- if(null != dpy) {
- dpy.validateEDT();
+ if( isNativeValid() ) {
+ screen.removeMonitorModeListener(monitorModeListenerImpl);
+ closeNativeImpl();
+ final AbstractGraphicsDevice cfgADevice = config.getScreen().getDevice();
+ if( cfgADevice != screen.getDisplay().getGraphicsDevice() ) { // don't pull display's device
+ cfgADevice.close(); // ensure a cfg's device is closed
}
+ setGraphicsConfiguration(null);
+ }
+ removeScreenReference();
+ Display dpy = screen.getDisplay();
+ if(null != dpy) {
+ dpy.validateEDTStopped();
}
// send synced destroyed notification
@@ -910,64 +1133,84 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
setWindowHandle(0);
visible = false;
fullscreen = false;
+ fullscreenMonitors = null;
+ fullscreenUseMainMonitor = true;
hasFocus = false;
parentWindowHandle = 0;
- windowLock.unlock();
+ _lock.unlock();
}
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
-
+
// these refs shall be kept alive - resurrection via setVisible(true)
/**
if(null!=parentWindow && parentWindow instanceof Window) {
((Window)parentWindow).removeChild(WindowImpl.this);
- }
+ }
childWindows = null;
surfaceUpdatedListeners = null;
mouseListeners = null;
keyListeners = null;
capsRequested = null;
lifecycleHook = null;
-
- screen = null;
+
+ screen = null;
windowListeners = null;
parentWindow = null;
- */
+ */
}
}
private final DestroyAction destroyAction = new DestroyAction();
+ @Override
public void destroy() {
- visible = false; // Immediately mark synchronized visibility flag, avoiding possible recreation
+ visible = false; // Immediately mark synchronized visibility flag, avoiding possible recreation
runOnEDTIfAvail(true, destroyAction);
}
+ protected void destroy(boolean preserveResources) {
+ if( null != lifecycleHook ) {
+ lifecycleHook.preserveGLStateAtDestroy( preserveResources );
+ }
+ destroy();
+ }
+
/**
* @param cWin child window, must not be null
* @param pWin parent window, may be null
- * @return true if at least one of both window's configurations is offscreen
+ * @return true if at least one of both window's configurations is offscreen
*/
protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) {
boolean ofs = false;
- if( null != cWin.getGraphicsConfiguration() ) {
- ofs = !cWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration();
+ if( null != cWinCfg ) {
+ ofs = !cWinCfg.getChosenCapabilities().isOnscreen();
}
- if( !ofs && null != pWin && null != pWin.getGraphicsConfiguration() ) {
- ofs |= !pWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ if( !ofs && null != pWin ) {
+ final AbstractGraphicsConfiguration pWinCfg = pWin.getGraphicsConfiguration();
+ if( null != pWinCfg ) {
+ ofs = !pWinCfg.getChosenCapabilities().isOnscreen();
+ }
}
return ofs;
}
-
+
private class ReparentAction implements Runnable {
- NativeWindow newParentWindow;
- boolean forceDestroyCreate;
+ final NativeWindow newParentWindow;
+ final int topLevelX, topLevelY;
+ final int hints;
ReparentOperation operation;
- private ReparentAction(NativeWindow newParentWindow, boolean forceDestroyCreate) {
+ private ReparentAction(NativeWindow newParentWindow, int topLevelX, int topLevelY, int hints) {
this.newParentWindow = newParentWindow;
- this.forceDestroyCreate = forceDestroyCreate | DEBUG_TEST_REPARENT_INCOMPATIBLE;
+ this.topLevelX = topLevelX;
+ this.topLevelY = topLevelY;
+ if( DEBUG_TEST_REPARENT_INCOMPATIBLE ) {
+ hints |= REPARENT_HINT_FORCE_RECREATION;
+ }
+ this.hints = hints;
this.operation = ReparentOperation.ACTION_INVALID; // ensure it's set
}
@@ -979,8 +1222,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
removeScreenReference();
screen = newScreen;
}
-
+
+ @Override
public final void run() {
+ if( WindowImpl.this.isFullscreen() ) {
+ // Bug 924: Ignore reparent when in fullscreen - otherwise may confuse WM
+ if( DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: NOP (in fullscreen, "+getThreadName()+") valid "+isNativeValid()+
+ ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+ }
+ return;
+ }
boolean animatorPaused = false;
if(null!=lifecycleHook) {
animatorPaused = lifecycleHook.pauseRenderingAction();
@@ -990,23 +1242,35 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
lifecycleHook.resumeRenderingAction();
}
}
-
+
private void reparent() {
// mirror pos/size so native change notification can get overwritten
- int x = getX();
- int y = getY();
- int width = getWidth();
- int height = getHeight();
- boolean wasVisible;
-
- windowLock.lock();
+ final int oldX = getX();
+ final int oldY = getY();
+ final int oldWidth = getWidth();
+ final int oldHeight = getHeight();
+ final int x, y;
+ int width = oldWidth;
+ int height = oldHeight;
+
+ final boolean wasVisible;
+ final boolean becomesVisible;
+ final boolean forceDestroyCreate;
+
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
- if(isNativeValid()) {
- // force recreation if offscreen, since it may become onscreen
- forceDestroyCreate |= isOffscreenInstance(WindowImpl.this, newParentWindow);
+ {
+ boolean v = 0 != ( REPARENT_HINT_FORCE_RECREATION & hints );
+ if(isNativeValid()) {
+ // force recreation if offscreen, since it may become onscreen
+ v |= isOffscreenInstance(WindowImpl.this, newParentWindow);
+ }
+ forceDestroyCreate = v;
}
-
+
wasVisible = isVisible();
+ becomesVisible = wasVisible || 0 != ( REPARENT_HINT_BECOMES_VISIBLE & hints );
Window newParentWindowNEWT = null;
if(newParentWindow instanceof Window) {
@@ -1015,15 +1279,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
long newParentWindowHandle = 0 ;
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", "+x+"/"+y+" "+width+"x"+height);
- }
-
- if(null!=lifecycleHook) {
- lifecycleHook.resetCounter();
+ if( DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+
+ ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+
+ ", visible "+wasVisible+", becomesVisible "+becomesVisible+
+ ", forceDestroyCreate "+forceDestroyCreate+
+ ", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+
+ ", HINT_FORCE_RECREATION "+( 0 != ( REPARENT_HINT_FORCE_RECREATION & hints ) )+
+ ", HINT_BECOMES_VISIBLE "+( 0 != ( REPARENT_HINT_BECOMES_VISIBLE & hints ) ) +
+ ", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+
+ ", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow) );
}
if(null!=newParentWindow) {
+ // REPARENT TO CHILD WINDOW
+
// reset position to 0/0 within parent space
x = 0;
y = 0;
@@ -1045,7 +1315,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
// Destroy this window and use parent's Screen.
// It may be created properly when the parent is made visible.
- destroy();
+ destroy( becomesVisible );
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
} else if(newParentWindow != getParent()) {
@@ -1056,25 +1326,24 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(null!=newParentWindowNEWT) {
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
} else {
- Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, getScreen());
- if( getScreen() != newScreen ) {
+ final Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, screen);
+ if( screen != newScreen ) {
// auto destroy on-the-fly created Screen/Display
setScreen( (ScreenImpl) newScreen );
}
}
- if( 0<width*height ) {
+ if( 0 < width && 0 < height ) {
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
}
- } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) {
- // Destroy this window, may create a new compatible Screen/Display,
- // and mark it for creation.
- destroy();
+ } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, screen) ) {
+ // Destroy this window, may create a new compatible Screen/Display, while trying to preserve resources if becoming visible again.
+ destroy( becomesVisible );
if(null!=newParentWindowNEWT) {
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
} else {
- setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, getScreen()) );
+ setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, screen) );
}
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
@@ -1086,12 +1355,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
operation = ReparentOperation.ACTION_NOP;
}
} else {
- if( null != parentWindow ) {
+ // REPARENT TO TOP-LEVEL WINDOW
+ if( 0 <= topLevelX && 0 <= topLevelY ) {
+ x = topLevelX;
+ y = topLevelY;
+ } else if( null != parentWindow ) {
// child -> top
// put client to current parent+child position
- Point p = getLocationOnScreen(null);
+ final Point p = getLocationOnScreen(null);
x = p.getX();
y = p.getY();
+ } else {
+ x = oldX;
+ y = oldY;
}
// Case: Top Window
@@ -1100,8 +1376,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
operation = ReparentOperation.ACTION_NOP;
} else if( !isNativeValid() || forceDestroyCreate ) {
// Destroy this window and mark it for [pending] creation.
- destroy();
- if( 0<width*height ) {
+ // If isNativeValid() and becoming visible again - try to preserve resources, i.e. b/c on-/offscreen switch.
+ destroy( becomesVisible );
+ if( 0 < width && 0 < height ) {
operation = ReparentOperation.ACTION_NATIVE_CREATION;
} else {
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
@@ -1117,15 +1394,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
throw new NativeWindowException("Internal Error: reparentAction not set");
}
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.reparent: ACTION ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", reparentAction "+operation+", pos/size "+x+"/"+y+" "+width+"x"+height+", visible "+wasVisible);
+ }
+
if( ReparentOperation.ACTION_NOP == operation ) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: NO CHANGE ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", visible "+wasVisible);
- }
return;
}
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparent: ACTION ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" new parentWindowHandle "+toHexString(newParentWindowHandle)+", reparentAction "+operation+", visible "+wasVisible);
+ if( null == newParentWindow ) {
+ // CLIENT -> TOP: Reset Parent's Pointer State
+ setOffscreenPointerIcon(null);
+ setOffscreenPointerVisible(true, null);
}
// rearrange window tree
@@ -1137,21 +1417,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
((Window)parentWindow).addChild(WindowImpl.this);
}
- if( ReparentOperation.ACTION_NATIVE_CREATION_PENDING == operation ) {
- // make size and position persistent for proper recreation
- definePosition(x, y);
- defineSize(width, height);
- return;
- }
-
if( ReparentOperation.ACTION_NATIVE_REPARENTING == operation ) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
- if(wasVisible) {
- setVisibleImpl(false, x, y, width, height);
- WindowImpl.this.waitForVisible(false, true);
- // some composite WM behave slacky .. give 'em chance to change state -> invisible,
+ // TOP -> CLIENT: !visible first (fixes X11 unsuccessful return to parent window)
+ if( null != parentWindow && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+ WindowImpl.this.waitForVisible(false, false);
+ // FIXME: Some composite WM behave slacky .. give 'em chance to change state -> invisible,
// even though we do exactly that (KDE+Composite)
try { Thread.sleep(100); } catch (InterruptedException e) { }
display.dispatchMessagesNative(); // status up2date
@@ -1177,46 +1451,72 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
parentWindowLocked.unlockSurface();
}
}
+ definePosition(x, y); // position might not get updated by WM events (SWT parent apparently)
// set visible again
if(ok) {
display.dispatchMessagesNative(); // status up2date
if(wasVisible) {
setVisibleImpl(true, x, y, width, height);
- ok = WindowImpl.this.waitForVisible(true, false);
- display.dispatchMessagesNative(); // status up2date
+ ok = 0 <= WindowImpl.this.waitForVisible(true, false);
if(ok) {
+ if( isAlwaysOnTop() && 0 == parentWindowHandle && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ // Reinforce ALWAYSONTOP when CHILD -> TOP reparenting, since reparenting itself cause X11 WM to loose it's state.
+ reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
}
if(ok) {
- requestFocusInt(false /* skipFocusAction */);
- display.dispatchMessagesNative(); // status up2date
+ if( 0 == parentWindowHandle ) {
+ // Position mismatch shall not lead to reparent failure
+ WindowImpl.this.waitForPosition(true, x, y, TIMEOUT_NATIVEWINDOW);
+ }
+
+ requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */);
+ display.dispatchMessagesNative(); // status up2date
}
}
}
if(!ok || !wasVisible) {
- // make size and position persistent manual,
+ // make size and position persistent manual,
// since we don't have a WM feedback (invisible or recreation)
definePosition(x, y);
defineSize(width, height);
}
-
+
if(!ok) {
- // native reparent failed -> try creation
+ // native reparent failed -> try creation, while trying to preserve resources if becoming visible again.
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation");
}
- destroy();
+ 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
+ // ACTION_NATIVE_CREATION
+ // ACTION_NATIVE_CREATION_PENDING;
+
+ // make size and position persistent for proper [re]creation
+ definePosition(x, y);
+ defineSize(width, height);
}
-
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+ System.err.println("Window.reparent: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
}
} finally {
- windowLock.unlock();
+ if(null!=lifecycleHook) {
+ lifecycleHook.resetCounter();
+ }
+ _lock.unlock();
}
if(wasVisible) {
switch (operation) {
@@ -1229,50 +1529,64 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// This may run on the new Display/Screen connection, hence a new EDT task
runOnEDTIfAvail(true, reparentActionRecreate);
break;
+
+ default:
}
}
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+x+"/"+y+" "+width+"x"+height);
+ System.err.println("Window.reparent: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
}
}
}
private class ReparentActionRecreate implements Runnable {
+ @Override
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
- visible = true;
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.reparentWindow: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
+ System.err.println("Window.reparent: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
}
- setVisible(true); // native creation
+ setVisibleActionImpl(true); // native creation
+ requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */);
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
}
}
private final ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate();
+ @Override
public final ReparentOperation reparentWindow(NativeWindow newParent) {
- return reparentWindow(newParent, false);
+ return reparentWindow(newParent, -1, -1, 0);
+ }
+
+ @Override
+ public final ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, boolean forceDestroyCreate) {
+ return reparentWindow(newParent, x, y, forceDestroyCreate ? REPARENT_HINT_FORCE_RECREATION : 0);
}
- public ReparentOperation reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) {
- final ReparentAction reparentAction = new ReparentAction(newParent, forceDestroyCreate);
+ @Override
+ public final ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints) {
+ final ReparentAction reparentAction = new ReparentAction(newParent, x, y, hints);
runOnEDTIfAvail(true, reparentAction);
return reparentAction.getOp();
}
- public CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
+ @Override
+ public final CapabilitiesChooser setCapabilitiesChooser(CapabilitiesChooser chooser) {
CapabilitiesChooser old = this.capabilitiesChooser;
this.capabilitiesChooser = chooser;
return old;
}
+ @Override
public final CapabilitiesImmutable getChosenCapabilities() {
return getGraphicsConfiguration().getChosenCapabilities();
}
+ @Override
public final CapabilitiesImmutable getRequestedCapabilities() {
return capsRequested;
}
@@ -1284,8 +1598,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.undecorated = undecorated;
}
+ @Override
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(WindowImpl.this.undecorated != undecorated) {
// set current state
@@ -1305,16 +1621,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
- public void setUndecorated(boolean value) {
+ @Override
+ public final void setUndecorated(boolean value) {
runOnEDTIfAvail(true, new DecorationAction(value));
}
+ @Override
public final boolean isUndecorated() {
return 0 != parentWindowHandle || undecorated || fullscreen ;
}
@@ -1326,13 +1644,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.alwaysOnTop = alwaysOnTop;
}
+ @Override
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(WindowImpl.this.alwaysOnTop != alwaysOnTop) {
// set current state
WindowImpl.this.alwaysOnTop = alwaysOnTop;
-
+
if( isNativeValid() ) {
// Mirror pos/size so native change notification can get overwritten
final int x = getX();
@@ -1347,24 +1667,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
+ @Override
public final void setAlwaysOnTop(boolean value) {
- runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
+ if( isFullscreen() ) {
+ nfs_alwaysOnTop = value;
+ } else {
+ runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
+ }
}
-
+
+ @Override
public final boolean isAlwaysOnTop() {
return alwaysOnTop;
}
-
- public String getTitle() {
+
+ @Override
+ public final String getTitle() {
return title;
}
- public void setTitle(String title) {
+ @Override
+ public final void setTitle(String title) {
if (title == null) {
title = "";
}
@@ -1374,25 +1702,122 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public boolean isPointerVisible() {
+ @Override
+ public final boolean isPointerVisible() {
return pointerVisible;
}
- public void setPointerVisible(boolean pointerVisible) {
+ @Override
+ 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;
+ 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(PixelRectangle, 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) {
+ final PointerIconImpl piImpl = (PointerIconImpl)pi;
+ if( this.pointerIcon != piImpl ) {
+ if( isNativeValid() ) {
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ setPointerIconIntern(piImpl);
+ } } );
+ }
+ this.pointerIcon = piImpl;
+ }
+ }
+ private void setPointerIconIntern(final PointerIconImpl pi) {
+ setOffscreenPointerIcon(pi);
+ setPointerIconImpl(pi);
+ }
+ /**
+ * Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to
+ * {@link OffscreenLayerSurface#setCursor(PixelRectangle, 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, pi.getHotspot());
+ } else {
+ return ols.setCursor(null, null); // default
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
}
}
+ return false;
}
- public boolean isPointerConfined() {
+
+ @Override
+ public final boolean isPointerConfined() {
return pointerConfined;
}
-
- public void confinePointer(boolean confine) {
+ @Override
+ public final void confinePointer(boolean confine) {
if(this.pointerConfined != confine) {
boolean setVal = 0 == getWindowHandle();
if(!setVal) {
@@ -1410,17 +1835,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
if(setVal) {
- this.pointerConfined = confine;
+ this.pointerConfined = confine;
}
- }
+ }
}
-
- public void warpPointer(int x, int y) {
+
+ @Override
+ public final void warpPointer(int x, int y) {
if(0 != getWindowHandle()) {
warpPointerImpl(x, y);
}
}
-
+
+ @Override
public final InsetsImmutable getInsets() {
if(isUndecorated()) {
return Insets.getZero();
@@ -1428,26 +1855,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
updateInsetsImpl(insets);
return insets;
}
-
+
+ @Override
public final int getWidth() {
return width;
}
+ @Override
public final int getHeight() {
return height;
}
+ @Override
public final int getX() {
return x;
}
+ @Override
public final int getY() {
return y;
}
protected final boolean autoPosition() { return autoPosition; }
-
- /** Sets the position fields {@link #x} and {@link #y} to the given values and {@link #autoPosition} to false. */
+
+ /** Sets the position fields {@link #x} and {@link #y} to the given values and {@link #autoPosition} to false. */
protected final void definePosition(int x, int y) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("definePosition: "+this.x+"/"+this.y+" -> "+x+"/"+y);
@@ -1457,7 +1888,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.x = x; this.y = y;
}
- /** Sets the size fields {@link #width} and {@link #height} to the given values. */
+ /** Sets the size fields {@link #width} and {@link #height} to the given values. */
protected final void defineSize(int width, int height) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("defineSize: "+this.width+"x"+this.height+" -> "+width+"x"+height);
@@ -1465,11 +1896,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
this.width = width; this.height = height;
}
-
+
+ @Override
public final boolean isVisible() {
return visible;
}
+ @Override
public final boolean isFullscreen() {
return fullscreen;
}
@@ -1478,6 +1911,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Window
//
+ @Override
+ public final Window getDelegatedWindow() {
+ return this;
+ }
+
+ //----------------------------------------------------------------------
+ // WindowImpl
+ //
+
/**
* If the implementation is capable of detecting a device change
* return true and clear the status/reason of the change.
@@ -1486,52 +1928,35 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return false;
}
- public LifecycleHook getLifecycleHook() {
+ public final LifecycleHook getLifecycleHook() {
return lifecycleHook;
}
- public LifecycleHook setLifecycleHook(LifecycleHook hook) {
+ public final LifecycleHook setLifecycleHook(LifecycleHook hook) {
LifecycleHook old = lifecycleHook;
lifecycleHook = hook;
return old;
}
- /** If this Window actually wraps one from another toolkit such as
- the AWT, this will return a non-null value. */
- public Object getWrappedWindow() {
- return null;
- }
-
- public final Window getDelegatedWindow() {
- return this;
- }
-
/**
- * If set to true, the default value, this NEWT Window implementation will
- * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify(boolean)} implementation.<br>
- * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify(boolean)}.
+ * If this Window actually wraps a {@link NativeSurface} from another instance or toolkit,
+ * it will return such reference. Otherwise returns null.
*/
- public void setHandleDestroyNotify(boolean b) {
- handleDestroyNotify = b;
+ public NativeSurface getWrappedSurface() {
+ return null;
}
- //----------------------------------------------------------------------
- // WindowImpl
- //
-
- /**
- * Returns the non delegated {@link AbstractGraphicsConfiguration},
- * see {@link #getGraphicsConfiguration()}. */
- public final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
- return config;
+ @Override
+ public final void setWindowDestroyNotifyAction(Runnable r) {
+ windowDestroyNotifyAction = r;
}
-
+
protected final long getParentWindowHandle() {
return isFullscreen() ? 0 : parentWindowHandle;
}
@Override
- public String toString() {
+ public final String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getName()+"[Config "+config+
@@ -1539,12 +1964,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
"\n, ParentWindow "+parentWindow+
"\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+
"\n, WindowHandle "+toHexString(getWindowHandle())+
- "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+isWindowLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
"\n, Pos "+getX()+"/"+getY()+" (auto "+autoPosition()+"), size "+getWidth()+"x"+getHeight()+
"\n, Visible "+isVisible()+", focus "+hasFocus()+
"\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+
"\n, AlwaysOnTop "+alwaysOnTop+", Fullscreen "+fullscreen+
- "\n, WrappedWindow "+getWrappedWindow()+
+ "\n, WrappedSurface "+getWrappedSurface()+
"\n, ChildWindows "+childWindows.size());
sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedHelper.size()+" [");
@@ -1559,12 +1984,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
for (int i = 0; i < mouseListeners.size(); i++ ) {
sb.append(mouseListeners.get(i)+", ");
}
+ sb.append("], PointerGestures default "+defaultGestureHandlerEnabled+", custom "+pointerGestureHandler.size()+" [");
+ for (int i = 0; i < pointerGestureHandler.size(); i++ ) {
+ sb.append(pointerGestureHandler.get(i)+", ");
+ }
sb.append("], KeyListeners num "+keyListeners.size()+" [");
for (int i = 0; i < keyListeners.size(); i++ ) {
sb.append(keyListeners.get(i)+", ");
}
- sb.append("], surfaceLock "+surfaceLock);
- sb.append(", windowLock "+windowLock+"]");
+ sb.append("], windowLock "+windowLock+", surfaceLockCount "+surfaceLockCount+"]");
return sb.toString();
}
@@ -1572,16 +2000,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
windowHandle = handle;
}
- public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- Screen scrn = getScreen();
- if(null==scrn) {
- throw new RuntimeException("Null screen of inner class: "+this);
+ @Override
+ public final void runOnEDTIfAvail(boolean wait, final Runnable task) {
+ if( windowLock.isOwner( Thread.currentThread() ) ) {
+ task.run();
+ } else {
+ ( (DisplayImpl) screen.getDisplay() ).runOnEDTIfAvail(wait, task);
}
- DisplayImpl d = (DisplayImpl) scrn.getDisplay();
- d.runOnEDTIfAvail(wait, task);
}
private final Runnable requestFocusAction = new Runnable() {
+ @Override
public final void run() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.RequestFocusAction: force 0 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -1590,6 +2019,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
};
private final Runnable requestFocusActionForced = new Runnable() {
+ @Override
public final void run() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.RequestFocusAction: force 1 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -1598,18 +2028,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
};
+ @Override
public final boolean hasFocus() {
return hasFocus;
}
- public void requestFocus() {
+ @Override
+ public final void requestFocus() {
requestFocus(true);
}
- public void requestFocus(boolean wait) {
+ @Override
+ public final void requestFocus(boolean wait) {
requestFocus(wait /* wait */, false /* skipFocusAction */, brokenFocusChange /* force */);
}
-
+
private void requestFocus(boolean wait, boolean skipFocusAction, boolean force) {
if( isNativeValid() &&
( force || !hasFocus() ) &&
@@ -1617,21 +2050,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
runOnEDTIfAvail(wait, force ? requestFocusActionForced : requestFocusAction);
}
}
-
+
/** Internally forcing request focus on current thread */
private void requestFocusInt(boolean skipFocusAction) {
if( skipFocusAction || !focusAction() ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+ System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): skipFocusAction "+skipFocusAction+", focus "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
}
requestFocusImpl(true);
- }
+ }
}
-
- public void setFocusAction(FocusRunnable focusAction) {
+
+ @Override
+ public final void setFocusAction(FocusRunnable focusAction) {
this.focusAction = focusAction;
}
-
+
private boolean focusAction() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.focusAction() START - "+getThreadName()+", focusAction: "+focusAction+" - windowHandle "+toHexString(getWindowHandle()));
@@ -1647,15 +2081,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
return res;
}
-
- protected void setBrokenFocusChange(boolean v) {
+
+ protected final void setBrokenFocusChange(boolean v) {
brokenFocusChange = v;
}
-
- public void setKeyboardFocusHandler(KeyListener l) {
+
+ @Override
+ public final void setKeyboardFocusHandler(KeyListener l) {
keyboardFocusHandler = l;
}
-
+
private class SetPositionAction implements Runnable {
int x, y;
@@ -1664,8 +2099,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
this.y = y;
}
+ @Override
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
try {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle));
@@ -1674,67 +2111,106 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(isNativeValid()) {
// this.x/this.y will be set by sizeChanged, triggered by windowing event system
reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
+ if( null == parentWindow ) {
+ // Wait until custom position is reached within tolerances
+ waitForPosition(true, x, y, Window.TIMEOUT_NATIVEWINDOW);
+ }
} else {
definePosition(x, y); // set pos for createNative(..)
}
}
} finally {
- windowLock.unlock();
+ _lock.unlock();
}
}
}
+ @Override
public void setPosition(int x, int y) {
autoPosition = false;
runOnEDTIfAvail(true, new SetPositionAction(x, y));
}
-
- public void setTopLevelPosition(int x, int y) {
+
+ @Override
+ public final void setTopLevelPosition(int x, int y) {
setPosition(x + getInsets().getLeftWidth(), y + getInsets().getTopHeight());
}
-
+
private class FullScreenAction implements Runnable {
- boolean fullscreen;
+ boolean _fullscreen;
- private boolean init(boolean fullscreen) {
+ private boolean init(boolean fullscreen) {
if(isNativeValid()) {
- this.fullscreen = fullscreen;
+ this._fullscreen = fullscreen;
return isFullscreen() != fullscreen;
} else {
WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..)
return false;
}
- }
- public boolean fsOn() { return fullscreen; }
+ }
+ public boolean fsOn() { return _fullscreen; }
+ @Override
public final void run() {
- windowLock.lock();
+ final RecursiveLock _lock = windowLock;
+ _lock.lock();
+ blockInsetsChange = true;
try {
- // set current state
- WindowImpl.this.fullscreen = fullscreen;
+ final int oldX = getX();
+ final int oldY = getY();
+ final int oldWidth = getWidth();
+ final int oldHeight = getHeight();
int x,y,w,h;
-
- if(fullscreen) {
- nfs_x = getX();
- nfs_y = getY();
- nfs_width = getWidth();
- nfs_height = getHeight();
- x = screen.getX();
- y = screen.getY();
- w = screen.getWidth();
- h = screen.getHeight();
+
+ final RectangleImmutable sviewport = screen.getViewport();
+ final RectangleImmutable viewport;
+ final int fs_span_flag;
+ final boolean alwaysOnTopChange;
+ if(_fullscreen) {
+ if( null == fullscreenMonitors ) {
+ if( fullscreenUseMainMonitor ) {
+ fullscreenMonitors = new ArrayList<MonitorDevice>();
+ fullscreenMonitors.add( getMainMonitor() );
+ } else {
+ fullscreenMonitors = getScreen().getMonitorDevices();
+ }
+ }
+ viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors);
+ if( isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) &&
+ ( fullscreenMonitors.size() > 1 || sviewport.compareTo(viewport) > 0 ) ) {
+ fs_span_flag = FLAG_IS_FULLSCREEN_SPAN;
+ } else {
+ fs_span_flag = 0;
+ }
+ nfs_x = oldX;
+ nfs_y = oldY;
+ nfs_width = oldWidth;
+ nfs_height = oldHeight;
+ nfs_alwaysOnTop = alwaysOnTop;
+ x = viewport.getX();
+ y = viewport.getY();
+ w = viewport.getWidth();
+ h = viewport.getHeight();
+ alwaysOnTop = false;
+ alwaysOnTopChange = nfs_alwaysOnTop != alwaysOnTop;
} else {
+ fullscreenUseMainMonitor = true;
+ fullscreenMonitors = null;
+ fs_span_flag = 0;
+ viewport = null;
x = nfs_x;
y = nfs_y;
w = nfs_width;
h = nfs_height;
-
+ alwaysOnTopChange = nfs_alwaysOnTop != alwaysOnTop;
+ alwaysOnTop = nfs_alwaysOnTop;
+
if(null!=parentWindow) {
// reset position to 0/0 within parent space
x = 0;
y = 0;
-
+
// refit if size is bigger than parent
if( w > parentWindow.getWidth() ) {
w = parentWindow.getWidth();
@@ -1744,14 +2220,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
+
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ final boolean wasVisible = isVisible();
+ final boolean tempInvisible = !_fullscreen && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true);
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen);
+ System.err.println("Window fs: "+_fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
+ ", virtl-screenSize: "+sviewport+", monitorsViewport "+viewport+
+ ", spanning "+(0!=fs_span_flag)+
+ ", alwaysOnTop "+alwaysOnTop+(alwaysOnTopChange?"*":"")+
+ ", wasVisible "+wasVisible+", tempInvisible "+tempInvisible+
+ ", hasParent "+(null!=parentWindow)+
+ " @ "+Thread.currentThread().getName());
+ }
+
+ // fullscreen off: !visible first (fixes X11 unsuccessful return to parent window _and_ wrong window size propagation)
+ if( tempInvisible ) {
+ setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+ WindowImpl.this.waitForVisible(false, false);
+ try { Thread.sleep(100); } catch (InterruptedException e) { }
+ display.dispatchMessagesNative(); // status up2date
}
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- display.dispatchMessagesNative(); // status up2date
- boolean wasVisible = isVisible();
-
// Lock parentWindow only during reparenting (attempt)
final NativeWindow parentWindowLocked;
if( null != parentWindow ) {
@@ -1763,81 +2255,127 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
parentWindowLocked = null;
}
try {
- reconfigureWindowImpl(x, y, w, h,
- getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
- FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) );
+ if(alwaysOnTopChange && _fullscreen) {
+ // Enter fullscreen - Disable alwaysOnTop
+ reconfigureWindowImpl(oldX, oldY, oldWidth, oldHeight, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
+
+ WindowImpl.this.fullscreen = _fullscreen;
+ reconfigureWindowImpl(x, y, w, h,
+ getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
+ fs_span_flag | FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, isVisible()) );
+ if(alwaysOnTopChange && !_fullscreen) {
+ // Leave fullscreen - Restore alwaysOnTop
+ reconfigureWindowImpl(x, y, w, h, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+ }
} finally {
if(null!=parentWindowLocked) {
parentWindowLocked.unlockSurface();
}
}
display.dispatchMessagesNative(); // status up2date
-
+
if(wasVisible) {
+ if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ // Give sluggy WM's (e.g. Unity) a chance to properly restore window ..
+ try { Thread.sleep(100); } catch (InterruptedException e) { }
+ display.dispatchMessagesNative(); // status up2date
+ }
setVisibleImpl(true, x, y, w, h);
- WindowImpl.this.waitForVisible(true, false);
- display.dispatchMessagesNative(); // status up2date
- WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
- display.dispatchMessagesNative(); // status up2date
-
+ boolean ok = 0 <= WindowImpl.this.waitForVisible(true, false);
+ if(ok) {
+ ok = WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
+ }
+ if(ok && !_fullscreen && null == parentWindow) {
+ // Position mismatch shall not lead to fullscreen failure
+ WindowImpl.this.waitForPosition(true, x, y, TIMEOUT_NATIVEWINDOW);
+ }
+ if(ok) {
+ requestFocusInt(_fullscreen /* skipFocusAction if fullscreen */);
+ display.dispatchMessagesNative(); // status up2date
+ }
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window fs done: " + WindowImpl.this);
+ System.err.println("Window fs done: ok " + ok + ", " + WindowImpl.this);
}
}
} finally {
- windowLock.unlock();
+ blockInsetsChange = false;
+ _lock.unlock();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
private final FullScreenAction fullScreenAction = new FullScreenAction();
+ @Override
public boolean setFullscreen(boolean fullscreen) {
+ return setFullscreenImpl(fullscreen, true, null);
+ }
+
+ @Override
+ public boolean setFullscreen(List<MonitorDevice> monitors) {
+ return setFullscreenImpl(true, false, monitors);
+ }
+
+ private boolean setFullscreenImpl(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
synchronized(fullScreenAction) {
- if( fullScreenAction.init(fullscreen) ) {
- if(fullScreenAction.fsOn() &&
- isOffscreenInstance(WindowImpl.this, parentWindow)) {
+ fullscreenMonitors = monitors;
+ fullscreenUseMainMonitor = useMainMonitor;
+ if( fullScreenAction.init(fullscreen) ) {
+ if( fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow) ) {
// enable fullscreen on offscreen instance
if(null != parentWindow) {
nfs_parent = parentWindow;
- reparentWindow(null, true);
+ reparentWindow(null, -1, -1, REPARENT_HINT_FORCE_RECREATION | REPARENT_HINT_BECOMES_VISIBLE);
} else {
throw new InternalError("Offscreen instance w/o parent unhandled");
}
}
-
+
runOnEDTIfAvail(true, fullScreenAction);
-
+
if(!fullScreenAction.fsOn() && null != nfs_parent) {
// disable fullscreen on offscreen instance
- reparentWindow(nfs_parent, true);
+ reparentWindow(nfs_parent, -1, -1, REPARENT_HINT_FORCE_RECREATION | REPARENT_HINT_BECOMES_VISIBLE);
nfs_parent = null;
}
-
- if(isVisible()) {
- requestFocus(true /* wait */, this.fullscreen /* skipFocusAction */, true /* force */);
- }
}
- return this.fullscreen;
+ return this.fullscreen;
}
}
- private class ScreenModeListenerImpl implements ScreenModeListener {
+ private class MonitorModeListenerImpl implements MonitorModeListener {
boolean animatorPaused = false;
-
- public void screenModeChangeNotify(ScreenMode sm) {
+ boolean hadFocus = false;
+ boolean fullscreenPaused = false;
+ List<MonitorDevice> _fullscreenMonitors = null;
+ boolean _fullscreenUseMainMonitor = true;
+
+ @Override
+ public void monitorModeChangeNotify(MonitorEvent me) {
+ hadFocus = hasFocus();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.screenModeChangeNotify: "+sm);
+ System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", "+me+" @ "+Thread.currentThread().getName());
}
if(null!=lifecycleHook) {
animatorPaused = lifecycleHook.pauseRenderingAction();
}
+ if( fullscreen && isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChangeNotify: FS Pause");
+ }
+ fullscreenPaused = true;
+ _fullscreenMonitors = fullscreenMonitors;
+ _fullscreenUseMainMonitor = fullscreenUseMainMonitor;
+ setFullscreenImpl(false, true, null);
+ }
}
- public void screenModeChanged(ScreenMode sm, boolean success) {
+ @Override
+ public void monitorModeChanged(MonitorEvent me, boolean success) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.screenModeChanged: "+sm+", success: "+success);
+ System.err.println("Window.monitorModeChanged: hadFocus "+hadFocus+", "+me+", success: "+success+" @ "+Thread.currentThread().getName());
}
if(success) {
@@ -1845,33 +2383,68 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Didn't pass above notify method. probably detected screen change after it happened.
animatorPaused = lifecycleHook.pauseRenderingAction();
}
- DimensionImmutable screenSize = sm.getMonitorMode().getSurfaceSize().getResolution();
- if ( getHeight() > screenSize.getHeight() ||
- getWidth() > screenSize.getWidth() ) {
- setSize(screenSize.getWidth(), screenSize.getHeight());
+ if( !fullscreen && !fullscreenPaused ) {
+ // Simply move/resize window to fit in virtual screen if required
+ final RectangleImmutable viewport = screen.getViewport();
+ if( viewport.getWidth() > 0 && viewport.getHeight() > 0 ) { // failsafe
+ final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ final RectangleImmutable isect = viewport.intersection(rect);
+ if ( getHeight() > isect.getHeight() ||
+ getWidth() > isect.getWidth() ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged: fit window "+rect+" into screen viewport "+viewport+
+ ", due to minimal intersection "+isect);
+ }
+ definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setSize(viewport.getWidth(), viewport.getHeight());
+ }
+ }
+ } else if( fullscreenPaused ){
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged: FS Restore");
+ }
+ setFullscreenImpl(true, _fullscreenUseMainMonitor, _fullscreenMonitors);
+ fullscreenPaused = false;
+ _fullscreenMonitors = null;
+ _fullscreenUseMainMonitor = true;
+ } else {
+ // If changed monitor is part of this fullscreen mode, reset size! (Bug 771)
+ final MonitorDevice md = me.getMonitor();
+ if( fullscreenMonitors.contains(md) ) {
+ final RectangleImmutable viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors);
+ if(DEBUG_IMPLEMENTATION) {
+ final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ System.err.println("Window.monitorModeChanged: FS Monitor Match: Fit window "+rect+" into new viewport union "+viewport+", provoked by "+md);
+ }
+ definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setFullscreenSize(viewport.getWidth(), viewport.getHeight());
+ }
}
}
-
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+ if( hadFocus ) {
+ requestFocus(true);
+ }
}
}
- private final ScreenModeListenerImpl screenModeListenerImpl = new ScreenModeListenerImpl();
-
+ private final MonitorModeListenerImpl monitorModeListenerImpl = new MonitorModeListenerImpl();
//----------------------------------------------------------------------
// Child Window Management
- //
+ //
+ @Override
public final boolean removeChild(NativeWindow win) {
synchronized(childWindowsLock) {
return childWindows.remove(win);
}
}
+ @Override
public final boolean addChild(NativeWindow win) {
if (win == null) {
return false;
@@ -1897,26 +2470,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
+ @Override
+ public final void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) {
if(isNativeValid()) {
- ((DisplayImpl)getScreen().getDisplay()).enqueueEvent(wait, event);
+ ((DisplayImpl)screen.getDisplay()).enqueueEvent(wait, event);
}
}
- public boolean consumeEvent(NEWTEvent e) {
+ @Override
+ public final boolean consumeEvent(NEWTEvent e) {
switch(e.getEventType()) {
// special repaint treatment
case WindowEvent.EVENT_WINDOW_REPAINT:
// queue repaint event in case window is locked, ie in operation
- if( isWindowLocked() ) {
+ if( null != windowLock.getOwner() ) {
// make sure only one repaint event is queued
if(!repaintQueued) {
repaintQueued=true;
final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+ System.err.println("Window.consumeEvent: REPAINT "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
// Thread.dumpStack();
- }
+ }
return discardTO; // discardTO:=true -> consumed
}
return true;
@@ -1927,10 +2502,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// common treatment
case WindowEvent.EVENT_WINDOW_RESIZED:
// queue event in case window is locked, ie in operation
- if( isWindowLocked() ) {
+ if( null != windowLock.getOwner() ) {
final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+ System.err.println("Window.consumeEvent: RESIZED "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
// Thread.dumpStack();
}
return discardTO; // discardTO:=true -> consumed
@@ -1944,7 +2519,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
} else if(e instanceof KeyEvent) {
consumeKeyEvent((KeyEvent)e);
} else if(e instanceof MouseEvent) {
- consumeMouseEvent((MouseEvent)e);
+ consumePointerEvent((MouseEvent)e);
} else {
throw new NativeWindowException("Unexpected NEWTEvent type " + e);
}
@@ -1952,160 +2527,638 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
//
- // SurfaceUpdatedListener Support
+ // MouseListener/Event Support
//
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
- }
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ //
+ // Native MouseEvents pre-processed to be enqueued or consumed directly
+ //
+
+ public void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(false, false, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+ }
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(true, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+ }
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
+ }
+ /**
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ doMouseEvent(false, false, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
}
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+ } */
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ /**
+ * Send mouse event (one-pointer) either to be directly consumed or to be enqueued
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ */
+ protected void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ if( 0 > button || button > MouseEvent.BUTTON_COUNT ) {
+ throw new NativeWindowException("Invalid mouse button number" + button);
+ }
+ doPointerEvent(enqueue, wait, constMousePointerTypes, eventType, modifiers,
+ 0 /*actionIdx*/, new short[] { (short)(button-1) },
+ new int[]{x}, new int[]{y}, new float[]{0f} /*pressure*/,
+ 1f /*maxPressure*/, rotationXYZ, rotationScale);
}
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ /**
+ * Send multiple-pointer event either to be directly consumed or to be enqueued
+ * <p>
+ * The index for the element of multiple-pointer arrays represents the pointer which triggered the event
+ * is passed via <i>actionIdx</i>.
+ * </p>
+ * <p>
+ * The given pointer names, <code>pNames</code>, are mapped to consecutive pointer IDs starting w/ 0
+ * using a hash-map if <code>normalPNames</code> is <code>false</code>.
+ * Otherwise a simple <code>int</code> to <code>short</code> type cast is performed.
+ * </p>
+ * <p>
+ * See {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, short[], int[], int[], float[], float, float[], float)}
+ * for details!
+ * </p>
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ * @param pTypes {@link MouseEvent.PointerType} for each pointer (multiple pointer)
+ * @param eventType
+ * @param modifiers
+ * @param actionIdx index of multiple-pointer arrays representing the pointer which triggered the event
+ * @param normalPNames see pName below.
+ * @param pNames Pointer name for each pointer (multiple pointer).
+ * We assume consecutive pointer names starting w/ 0 if <code>normalPIDs</code> is <code>true</code>.
+ * Otherwise we hash-map the values during state pressed to retrieve the normal ID.
+ * @param pX X-axis for each pointer (multiple pointer)
+ * @param pY Y-axis for each pointer (multiple pointer)
+ * @param pPressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ */
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, final int modifiers,
+ final int actionIdx, final boolean normalPNames, final int[] pNames,
+ final int[] pX, final int[] pY, final float[] pPressure,
+ float maxPressure, final float[] rotationXYZ, final float rotationScale) {
+ final int pCount = pNames.length;
+ final short[] pIDs = new short[pCount];
+ for(int i=0; i<pCount; i++) {
+ if( !normalPNames ) {
+ // hash map int name -> short idx
+ final int sz0 = pName2pID.size();
+ final Integer pNameI1 = pName2pID.getOrAdd(Integer.valueOf(pNames[i]));
+ final short pID = (short)pName2pID.indexOf(pNameI1);
+ pIDs[i] = pID;
+ if(DEBUG_MOUSE_EVENT) {
+ final int sz1 = pName2pID.size();
+ if( sz0 != sz1 ) {
+ System.err.println("PointerName2ID[sz "+sz1+"]: Map "+pNameI1+" == "+pID);
+ }
+ }
+ if( MouseEvent.EVENT_MOUSE_RELEASED == eventType ) {
+ pName2pID.remove(pNameI1);
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("PointerName2ID[sz "+pName2pID.size()+"]: Unmap "+pNameI1+" == "+pID);
+ }
+ }
+ } else {
+ // simple type cast
+ pIDs[i] = (short)pNames[i];
+ }
+ }
+ doPointerEvent(enqueue, wait, pTypes, eventType, modifiers, actionIdx, pIDs,
+ pX, pY, pPressure, maxPressure, rotationXYZ, rotationScale);
}
- //
- // MouseListener/Event Support
- //
- public void sendMouseEvent(int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation);
- }
- public void enqueueMouseEvent(boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation);
- }
-
- protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- if(eventType == MouseEvent.EVENT_MOUSE_ENTERED ||
- eventType == MouseEvent.EVENT_MOUSE_EXITED) {
- if(eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1) {
- x = lastMousePosition.getX();
- y = lastMousePosition.getY();
- }
- // clip coordinates to window dimension
- x = Math.min(Math.max(x, 0), getWidth()-1);
- y = Math.min(Math.max(y, 0), getHeight()-1);
- mouseInWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED;
- lastMousePressed=0; // clear state
- mouseButtonPressed=0; // clear state
- }
- if(x<0||y<0||x>=getWidth()||y>=getHeight()) {
+ /**
+ * Send multiple-pointer event either to be directly consumed or to be enqueued.
+ * <p>
+ * Pointer/Mouse Processing Pass 1 (Pass 2 is performed in {@link #consumePointerEvent(MouseEvent)}.
+ * </p>
+ * <p>
+ * Usually directly called by event source to enqueue and process event.
+ * </p>
+ * <p>
+ * The index for the element of multiple-pointer arrays represents the pointer which triggered the event
+ * is passed via <i>actionIdx</i>.
+ * </p>
+ * <p>
+ * <ul>
+ * <li>Determine ENTERED/EXITED state</li>
+ * <li>Remove redundant move/drag events</li>
+ * <li>Reset states if applicable</li>
+ * <li>Drop exterior events</li>
+ * <li>Determine CLICK COUNT</li>
+ * <li>Ignore sent CLICKED</li>
+ * <li>Track buttonPressed incl. buttonPressedMask</li>
+ * <li>Synthesize DRAGGED event (from MOVED if pointer is pressed)</li>
+ * </ul>
+ * </p>
+ *
+ * @param enqueue if true, event will be {@link #enqueueEvent(boolean, NEWTEvent) enqueued},
+ * otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
+ * @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
+ * @param pTypes {@link MouseEvent.PointerType} for each pointer (multiple pointer)
+ * @param eventType
+ * @param modifiers
+ * @param pActionIdx index of multiple-pointer arrays representing the pointer which triggered the event
+ * @param pID Pointer ID for each pointer (multiple pointer). We assume consecutive pointerIDs starting w/ 0.
+ * A pointer-ID of -1 may also denote no pointer/button activity, i.e. {@link PointerType#Mouse} move.
+ * @param pX X-axis for each pointer (multiple pointer)
+ * @param pY Y-axis for each pointer (multiple pointer)
+ * @param pPressure Pressure for each pointer (multiple pointer)
+ * @param maxPressure Maximum pointer pressure for all pointer
+ */
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, int modifiers,
+ final int pActionIdx, final short[] pID, final int[] pX, final int[] pY, final float[] pPressure,
+ final float maxPressure, final float[] rotationXYZ, final float rotationScale) {
+ final long when = System.currentTimeMillis();
+ final int pCount = pTypes.length;
+
+ if( 0 > pActionIdx || pActionIdx >= pCount) {
+ throw new IllegalArgumentException("actionIdx out of bounds [0.."+(pCount-1)+"]");
+ }
+ if( 0 < pActionIdx ) {
+ // swap values to make idx 0 the triggering pointer
+ {
+ final PointerType aType = pTypes[pActionIdx];
+ pTypes[pActionIdx] = pTypes[0];
+ pTypes[0] = aType;
+ }
+ {
+ final short s = pID[pActionIdx];
+ pID[pActionIdx] = pID[0];
+ pID[0] = s;
+ }
+ {
+ int s = pX[pActionIdx];
+ pX[pActionIdx] = pX[0];
+ pX[0] = s;
+ s = pY[pActionIdx];
+ pY[pActionIdx] = pY[0];
+ pY[0] = s;
+ }
+ {
+ final float aPress = pPressure[pActionIdx];
+ pPressure[pActionIdx] = pPressure[0];
+ pPressure[0] = aPress;
+ }
+ }
+ final short id = pID[0];
+ final short button;
+ {
+ final int b = id + 1;
+ if( 0 <= b && b <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) { // we allow id==-1 -> button==0 for no button, i.e. mouse move
+ button = (short)b;
+ } else {
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
+ }
+
+ //
+ // - Determine ENTERED/EXITED state
+ // - Remove redundant move/drag events
+ // - Reset states if applicable
+ //
+ int x = pX[0];
+ int y = pY[0];
+ final boolean insideWindow = x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
+ final Point movePositionP0 = pState1.getMovePosition(id);
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState1.dragging ) {
+ // Drop mouse EXIT if dragging, i.e. due to exterior dragging outside of window.
+ // NOTE-1: X11 produces the 'premature' EXIT, however it also produces 'EXIT' after exterior dragging!
+ // NOTE-2: consumePointerEvent(MouseEvent) will synthesize a missing EXIT event!
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to dragging: "+pState1);
+ }
+ return;
+ }
+ if( null != movePositionP0 ) {
+ if( x==-1 && y==-1 ) {
+ x = movePositionP0.getX();
+ y = movePositionP0.getY();
+ }
+ movePositionP0.set(0, 0);
+ }
+ // Fall through intended!
+
+ case MouseEvent.EVENT_MOUSE_ENTERED:
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ pState1.insideWindow = true;
+ pState1.exitSent = false;
+ } else {
+ pState1.insideWindow = false;
+ pState1.exitSent = true;
+ }
+ pState1.clearButton();
+ if( pTypes[0] != PointerType.Mouse ) {
+ // Drop !MOUSE ENTER/EXIT Events - Safeguard for non compliant implementations only.
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to !Mouse but "+pTypes[0]+": "+pState1);
+ }
+ return;
+ }
+ // clip coordinates to window dimension
+ x = Math.min(Math.max(x, 0), getWidth()-1);
+ y = Math.min(Math.max(y, 0), getHeight()-1);
+ break;
+
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ if( null != movePositionP0 ) {
+ if( movePositionP0.getX() == x && movePositionP0.getY() == y ) {
+ // Drop same position
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" w/ same position: "+movePositionP0+", "+pState1);
+ }
+ return;
+ }
+ movePositionP0.set(x, y);
+ }
+
+ // Fall through intended !
+
+ default:
+ if( pState1.insideWindow != insideWindow ) {
+ // ENTER/EXIT!
+ pState1.insideWindow = insideWindow;
+ if( insideWindow ) {
+ pState1.exitSent = false;
+ }
+ pState1.clearButton();
+ }
+ }
+
+ //
+ // Drop exterior events if not dragging pointer and not EXIT event
+ // Safeguard for non compliant implementations!
+ //
+ if( !pState1.dragging && !insideWindow && MouseEvent.EVENT_MOUSE_EXITED != eventType ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop: "+MouseEvent.getEventTypeString(eventType)+
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", insideWindow "+insideWindow+", "+pState1);
+ }
return; // .. invalid ..
}
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
- ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+lastMousePosition);
- }
- long when = System.currentTimeMillis();
- MouseEvent eEntered = null;
- if(eventType == MouseEvent.EVENT_MOUSE_MOVED) {
- if(!mouseInWindow) {
- mouseInWindow = true;
- eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- lastMousePressed=0; // clear state
- mouseButtonPressed=0; // clear state
- } else if(lastMousePosition.getX() == x && lastMousePosition.getY()==y) {
+ System.err.println("doPointerEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", "+pState1);
+ }
+
+ final int buttonMask = InputEvent.getButtonMask(button);
+ modifiers |= buttonMask; // Always add current button to modifier mask (Bug 571)
+ modifiers |= pState1.buttonPressedMask; // Always add currently pressed mouse buttons to modifier mask
+
+ if( isPointerConfined() ) {
+ modifiers |= InputEvent.CONFINED_MASK;
+ }
+ if( !isPointerVisible() ) {
+ modifiers |= InputEvent.INVISIBLE_MASK;
+ }
+
+ pX[0] = x;
+ pY[0] = y;
+
+ //
+ // - Determine CLICK COUNT
+ // - Ignore sent CLICKED
+ // - Track buttonPressed incl. buttonPressedMask
+ // - Synthesize DRAGGED event (from MOVED if pointer is pressed)
+ //
+ final MouseEvent e;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ e = null;
+ break;
+
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ if( 0 >= pPressure[0] ) {
+ pPressure[0] = maxPressure;
+ }
+ pState1.buttonPressedMask |= buttonMask;
+ if( 1 == pCount ) {
+ if( when - pState1.lastButtonPressTime < MouseEvent.getClickTimeout() ) {
+ pState1.lastButtonClickCount++;
+ } else {
+ pState1.lastButtonClickCount=(short)1;
+ }
+ pState1.lastButtonPressTime = when;
+ pState1.buttonPressed = button;
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, pState1.lastButtonClickCount, rotationXYZ, rotationScale);
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)1, rotationXYZ, rotationScale);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ pState1.buttonPressedMask &= ~buttonMask;
+ if( 1 == pCount ) {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, pState1.lastButtonClickCount, rotationXYZ, rotationScale);
+ if( when - pState1.lastButtonPressTime >= MouseEvent.getClickTimeout() ) {
+ pState1.lastButtonClickCount = (short)0;
+ pState1.lastButtonPressTime = 0;
+ }
+ pState1.buttonPressed = 0;
+ pState1.dragging = false;
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)1, rotationXYZ, rotationScale);
+ if( 0 == pState1.buttonPressedMask ) {
+ pState1.clearButton();
+ }
+ }
+ if( null != movePositionP0 ) {
+ movePositionP0.set(0, 0);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ if ( 0 != pState1.buttonPressedMask ) { // any button or pointer move -> drag
+ e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, pState1.buttonPressed, (short)1, rotationXYZ, rotationScale);
+ pState1.dragging = true;
+ } else {
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)0, rotationXYZ, rotationScale);
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ if( 0 >= pPressure[0] ) {
+ pPressure[0] = maxPressure;
+ }
+ pState1.dragging = true;
+ // Fall through intended!
+ default:
+ e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
+ pX, pY, pPressure, maxPressure, button, (short)0, rotationXYZ, rotationScale);
+ }
+ doEvent(enqueue, wait, e); // actual mouse event
+ }
+
+ private static int step(int lower, int edge, int value) {
+ return value < edge ? lower : value;
+ }
+
+ /**
+ * Consume the {@link MouseEvent}.
+ * <p>
+ * Pointer/Mouse Processing Pass 2 (Pass 1 is performed in {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, short[], int[], int[], float[], float, float[], float)}).
+ * </p>
+ * <p>
+ * Invoked before dispatching the dequeued event.
+ * </p>
+ * <p>
+ * <ul>
+ * <li>Validate</li>
+ * <li>Handle gestures</li>
+ * <li>Synthesize events [ENTERED, EXIT, CLICK] and gestures.</li>
+ * <li>Drop exterior events</li>
+ * <li>Dispatch event to listener</li>
+ * </ul>
+ * </p>
+ */
+ protected void consumePointerEvent(MouseEvent pe) {
+ int x = pe.getX();
+ int y = pe.getY();
+
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.in: "+pe+", "+pState0+", pos "+x+"/"+y+" clientSize["+getWidth()+"x"+getHeight()+"]");
+ }
+
+ //
+ // - Determine ENTERED/EXITED state
+ // - Synthesize ENTERED and EXIT event
+ // - Reset states if applicable
+ //
+ final long when = pe.getWhen();
+ final int eventType = pe.getEventType();
+ final boolean insideWindow;
+ boolean eExitAllowed = false;
+ MouseEvent eEntered = null, eExited = null;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState0.exitSent || pState0.dragging ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent: drop "+(pState0.exitSent?"already sent":"due to dragging")+": "+pe+", "+pState0);
+ }
+ return;
+ }
+ // Fall through intended !
+ case MouseEvent.EVENT_MOUSE_ENTERED:
+ // clip coordinates to window dimension
+ x = Math.min(Math.max(x, 0), getWidth()-1);
+ y = Math.min(Math.max(y, 0), getHeight()-1);
+ pState0.clearButton();
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ insideWindow = true;
+ pState0.insideWindow = true;
+ pState0.exitSent = false;
+ pState0.dragging = false;
+ } else {
+ insideWindow = false;
+ pState0.insideWindow = false;
+ pState0.exitSent = true;
+ }
+ break;
+
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ if( 1 >= pe.getButtonDownCount() ) { // MOVE or RELEASE last button
+ eExitAllowed = !pState0.exitSent;
+ pState0.dragging = false;
+ }
+ // Fall through intended !
+
+ default:
+ insideWindow = x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
+ if( pe.getPointerType(0) == PointerType.Mouse ) {
+ if( !pState0.insideWindow && insideWindow ) {
+ // ENTER .. use clipped coordinates
+ eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(x, 0), getWidth()-1),
+ Math.min(Math.max(y, 0), getHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = false;
+ } else if( !insideWindow && eExitAllowed ) {
+ // EXIT .. use clipped coordinates
+ eExited = new MouseEvent(MouseEvent.EVENT_MOUSE_EXITED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(x, 0), getWidth()-1),
+ Math.min(Math.max(y, 0), getHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = true;
+ }
+ }
+ if( pState0.insideWindow != insideWindow || null != eEntered || null != eExited) {
+ pState0.clearButton();
+ }
+ pState0.insideWindow = insideWindow;
+ }
+ if( null != eEntered ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.send.0: "+eEntered+", "+pState0);
+ }
+ dispatchMouseEvent(eEntered);
+ } else if( DEBUG_MOUSE_EVENT && !insideWindow ) {
+ System.err.println("INFO consumePointerEvent.exterior: "+pState0+", "+pe);
+ }
+
+ //
+ // Handle Default Gestures
+ //
+ if( defaultGestureHandlerEnabled &&
+ pe.getPointerType(0).getPointerClass() == MouseEvent.PointerClass.Onscreen )
+ {
+ if( null == gesture2PtrTouchScroll ) {
+ final int scaledScrollSlop;
+ final int scaledDoubleTapSlop;
+ final MonitorDevice monitor = getMainMonitor();
+ if ( null != monitor ) {
+ final DimensionImmutable mm = monitor.getSizeMM();
+ final float pixWPerMM = (float)monitor.getCurrentMode().getRotatedWidth() / (float)mm.getWidth();
+ final float pixHPerMM = (float)monitor.getCurrentMode().getRotatedHeight() / (float)mm.getHeight();
+ final float pixPerMM = Math.min(pixHPerMM, pixWPerMM);
+ scaledScrollSlop = Math.round(DoubleTapScrollGesture.SCROLL_SLOP_MM * pixPerMM);
+ scaledDoubleTapSlop = Math.round(DoubleTapScrollGesture.DOUBLE_TAP_SLOP_MM * pixPerMM);
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.gscroll: scrollSlop "+scaledScrollSlop+", doubleTapSlop "+scaledDoubleTapSlop+", pixPerMM "+pixPerMM+", "+monitor+", "+pState0);
+ }
+ } else {
+ scaledScrollSlop = DoubleTapScrollGesture.SCROLL_SLOP_PIXEL;
+ scaledDoubleTapSlop = DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL;
+ }
+ gesture2PtrTouchScroll = new DoubleTapScrollGesture(step(DoubleTapScrollGesture.SCROLL_SLOP_PIXEL, DoubleTapScrollGesture.SCROLL_SLOP_PIXEL/2, scaledScrollSlop),
+ step(DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL, DoubleTapScrollGesture.DOUBLE_TAP_SLOP_PIXEL/2, scaledDoubleTapSlop));
+ }
+ if( gesture2PtrTouchScroll.process(pe) ) {
+ pe = (MouseEvent) gesture2PtrTouchScroll.getGestureEvent();
+ gesture2PtrTouchScroll.clear(false);
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: skip EVENT_MOUSE_MOVED w/ same position: "+lastMousePosition);
+ System.err.println("consumePointerEvent.gscroll: "+pe+", "+pState0);
+ }
+ dispatchMouseEvent(pe);
+ return;
+ }
+ if( gesture2PtrTouchScroll.isWithinGesture() ) {
+ return; // within gesture .. need more input ..
+ }
+ }
+ //
+ // Handle Custom Gestures
+ //
+ {
+ final int pointerGestureHandlerCount = pointerGestureHandler.size();
+ if( pointerGestureHandlerCount > 0 ) {
+ boolean withinGesture = false;
+ for(int i = 0; !pe.isConsumed() && i < pointerGestureHandlerCount; i++ ) {
+ final GestureHandler gh = pointerGestureHandler.get(i);
+ if( gh.process(pe) ) {
+ final InputEvent ieG = gh.getGestureEvent();
+ gh.clear(false);
+ if( ieG instanceof MouseEvent ) {
+ dispatchMouseEvent((MouseEvent)ieG);
+ } else if( ieG instanceof GestureHandler.GestureEvent) {
+ final GestureHandler.GestureEvent ge = (GestureHandler.GestureEvent) ieG;
+ for(int j = 0; !ge.isConsumed() && j < gestureListeners.size(); j++ ) {
+ gestureListeners.get(j).gestureDetected(ge);
+ }
+ }
+ return;
+ }
+ withinGesture |= gh.isWithinGesture();
+ }
+ if( withinGesture ) {
+ return;
}
- return; // skip same position
}
- lastMousePosition.setX(x);
- lastMousePosition.setY(y);
- }
- if( 0 > button || button > MouseEvent.BUTTON_NUMBER ) {
- throw new NativeWindowException("Invalid mouse button number" + button);
}
- // Fixes Bug 571: X11 behavior, where the PRESSED button is not included in the native mask.
- modifiers |= InputEvent.getButtonMask(button);
+ //
+ // - Synthesize mouse CLICKED
+ // - Ignore sent CLICKED
+ //
MouseEvent eClicked = null;
- MouseEvent e = null;
+ switch( eventType ) {
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ if( 1 == pe.getPointerCount() ) {
+ pState0.lastButtonPressTime = when;
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ if( 1 == pe.getPointerCount() && when - pState0.lastButtonPressTime < MouseEvent.getClickTimeout() ) {
+ eClicked = pe.createVariant(MouseEvent.EVENT_MOUSE_CLICKED);
+ } else {
+ pState0.lastButtonPressTime = 0;
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_CLICKED:
+ // ignore - synthesized here ..
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent: drop recv'ed (synth here) "+pe+", "+pState0);
+ }
+ pe = null;
+ break;
- if(isPointerConfined()) {
- modifiers |= InputEvent.CONFINED_MASK;
- }
- if(!isPointerVisible()) {
- modifiers |= InputEvent.INVISIBLE_MASK;
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ pState0.dragging = true;
+ break;
}
-
- if(MouseEvent.EVENT_MOUSE_PRESSED==eventType) {
- if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
- lastMouseClickCount++;
- } else {
- lastMouseClickCount=1;
- }
- lastMousePressed=when;
- mouseButtonPressed=button;
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- } else if(MouseEvent.EVENT_MOUSE_RELEASED==eventType) {
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- if(when-lastMousePressed<MouseEvent.getClickTimeout()) {
- eClicked = new MouseEvent(MouseEvent.EVENT_MOUSE_CLICKED, this, when,
- modifiers, x, y, lastMouseClickCount, button, 0);
- } else {
- lastMouseClickCount=0;
- lastMousePressed=0;
- }
- mouseButtonPressed=0;
- } else if(MouseEvent.EVENT_MOUSE_MOVED==eventType) {
- if (mouseButtonPressed>0) {
- e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when,
- modifiers, x, y, 1, mouseButtonPressed, 0);
- } else {
- e = new MouseEvent(eventType, this, when,
- modifiers, x, y, 0, button, 0);
+
+ if( null != pe ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.send.1: "+pe+", "+pState0);
}
- } else if(MouseEvent.EVENT_MOUSE_WHEEL_MOVED==eventType) {
- e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, rotation);
- } else {
- e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0);
+ dispatchMouseEvent(pe); // actual mouse event
}
- if(null!=eEntered) {
+ if( null != eClicked ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: synthesized MOUSE_ENTERED event: "+eEntered);
+ System.err.println("consumePointerEvent.send.2: "+eClicked+", "+pState0);
}
- doEvent(enqueue, wait, eEntered);
+ dispatchMouseEvent(eClicked);
}
- doEvent(enqueue, wait, e); // actual mouse event
- if(null!=eClicked) {
+ if( null != eExited ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doMouseEvent: synthesized MOUSE_CLICKED event: "+eClicked);
+ System.err.println("consumePointerEvent.send.3: "+eExited+", "+pState0);
}
- doEvent(enqueue, wait, eClicked);
+ dispatchMouseEvent(eExited);
}
}
-
- public void addMouseListener(MouseListener l) {
+ @Override
+ public final void addMouseListener(MouseListener l) {
addMouseListener(-1, l);
}
- public void addMouseListener(int index, MouseListener l) {
+ @Override
+ public final void addMouseListener(int index, MouseListener l) {
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
- if(0>index) {
- index = clonedListeners.size();
+ if(0>index) {
+ index = clonedListeners.size();
}
clonedListeners.add(index, l);
mouseListeners = clonedListeners;
}
- public void removeMouseListener(MouseListener l) {
+ @Override
+ public final void removeMouseListener(MouseListener l) {
if (l == null) {
return;
}
@@ -2115,25 +3168,87 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
mouseListeners = clonedListeners;
}
- public MouseListener getMouseListener(int index) {
+ @Override
+ public final MouseListener getMouseListener(int index) {
@SuppressWarnings("unchecked")
ArrayList<MouseListener> clonedListeners = (ArrayList<MouseListener>) mouseListeners.clone();
- if(0>index) {
- index = clonedListeners.size()-1;
+ if(0>index) {
+ index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public MouseListener[] getMouseListeners() {
+ @Override
+ public final MouseListener[] getMouseListeners() {
return mouseListeners.toArray(new MouseListener[mouseListeners.size()]);
}
- protected void consumeMouseEvent(MouseEvent e) {
- if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumeMouseEvent: event: "+e);
+ @Override
+ public final void setDefaultGesturesEnabled(boolean enable) {
+ defaultGestureHandlerEnabled = enable;
+ }
+ @Override
+ public final boolean areDefaultGesturesEnabled() {
+ return defaultGestureHandlerEnabled;
+ }
+
+ @Override
+ public final void addGestureHandler(GestureHandler gh) {
+ addGestureHandler(-1, gh);
+ }
+ @Override
+ public final void addGestureHandler(int index, GestureHandler gh) {
+ if(gh == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ ArrayList<GestureHandler> cloned = (ArrayList<GestureHandler>) pointerGestureHandler.clone();
+ if(0>index) {
+ index = cloned.size();
+ }
+ cloned.add(index, gh);
+ pointerGestureHandler = cloned;
+ }
+ @Override
+ public final void removeGestureHandler(GestureHandler gh) {
+ if (gh == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ ArrayList<GestureHandler> cloned = (ArrayList<GestureHandler>) pointerGestureHandler.clone();
+ cloned.remove(gh);
+ pointerGestureHandler = cloned;
+ }
+ @Override
+ public final void addGestureListener(GestureHandler.GestureListener gl) {
+ addGestureListener(-1, gl);
+ }
+ @Override
+ public final void addGestureListener(int index, GestureHandler.GestureListener gl) {
+ if(gl == null) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ ArrayList<GestureHandler.GestureListener> cloned = (ArrayList<GestureHandler.GestureListener>) gestureListeners.clone();
+ if(0>index) {
+ index = cloned.size();
+ }
+ cloned.add(index, gl);
+ gestureListeners = cloned;
+ }
+ @Override
+ public final void removeGestureListener(GestureHandler.GestureListener gl) {
+ if (gl == null) {
+ return;
}
- boolean consumed = false;
- for(int i = 0; !consumed && i < mouseListeners.size(); i++ ) {
+ @SuppressWarnings("unchecked")
+ ArrayList<GestureHandler.GestureListener> cloned = (ArrayList<GestureHandler.GestureListener>) gestureListeners.clone();
+ cloned.remove(gl);
+ gestureListeners= cloned;
+ }
+
+ private final void dispatchMouseEvent(MouseEvent e) {
+ for(int i = 0; !e.isConsumed() && i < mouseListeners.size(); i++ ) {
MouseListener l = mouseListeners.get(i);
switch(e.getEventType()) {
case MouseEvent.EVENT_MOUSE_CLICKED:
@@ -2163,39 +3278,113 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
default:
throw new NativeWindowException("Unexpected mouse event type " + e.getEventType());
}
- consumed = InputEvent.consumedTag == e.getAttachment();
}
}
//
// KeyListener/Event Support
//
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+ private static final int keyTrackingRange = 255;
+ private final IntBitfield keyPressedState = new IntBitfield( keyTrackingRange + 1 );
+
+ protected final boolean isKeyCodeTracked(final short keyCode) {
+ return ( 0xFFFF & keyCode ) <= keyTrackingRange;
}
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- enqueueEvent(wait, new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) );
+ /**
+ * @param keyCode the keyCode to set pressed state
+ * @param pressed true if pressed, otherwise false
+ * @return the previus pressed value
+ */
+ protected final boolean setKeyPressed(short keyCode, boolean pressed) {
+ final int v = 0xFFFF & keyCode;
+ if( v <= keyTrackingRange ) {
+ return keyPressedState.put(v, pressed);
+ }
+ return false;
+ }
+ /**
+ * @param keyCode the keyCode to test pressed state
+ * @return true if pressed, otherwise false
+ */
+ protected final boolean isKeyPressed(short keyCode) {
+ final int v = 0xFFFF & keyCode;
+ if( v <= keyTrackingRange ) {
+ return keyPressedState.get(v);
+ }
+ return false;
}
- public void addKeyListener(KeyListener l) {
+ public void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ // Always add currently pressed mouse buttons to modifier mask
+ consumeKeyEvent( KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) );
+ }
+
+ public void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ // Always add currently pressed mouse buttons to modifier mask
+ enqueueEvent(wait, KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) );
+ }
+
+ @Override
+ public final void setKeyboardVisible(boolean visible) {
+ if(isNativeValid()) {
+ // We don't skip the impl. if it seems that there is no state change,
+ // since we cannot assume the impl. reliably gives us it's current state.
+ final boolean ok = setKeyboardVisibleImpl(visible);
+ if(DEBUG_IMPLEMENTATION || DEBUG_KEY_EVENT) {
+ System.err.println("setKeyboardVisible(native): visible "+keyboardVisible+" -- op[visible:"+visible +", ok "+ok+"] -> "+(visible && ok));
+ }
+ keyboardVisibilityChanged( visible && ok );
+ } else {
+ keyboardVisibilityChanged( visible ); // earmark for creation
+ }
+ }
+ @Override
+ public final boolean isKeyboardVisible() {
+ return keyboardVisible;
+ }
+ /**
+ * Returns <code>true</code> if operation was successful, otherwise <code>false</code>.
+ * <p>
+ * We assume that a failed invisible operation is due to an already invisible keyboard,
+ * hence even if an invisible operation failed, the keyboard is considered invisible!
+ * </p>
+ */
+ protected boolean setKeyboardVisibleImpl(boolean visible) {
+ return false; // nop
+ }
+ /** Triggered by implementation's WM events to update the virtual on-screen keyboard's visibility state. */
+ protected void keyboardVisibilityChanged(boolean visible) {
+ if(keyboardVisible != visible) {
+ if(DEBUG_IMPLEMENTATION || DEBUG_KEY_EVENT) {
+ System.err.println("keyboardVisibilityChanged: "+keyboardVisible+" -> "+visible);
+ }
+ keyboardVisible = visible;
+ }
+ }
+ protected boolean keyboardVisible = false;
+
+ @Override
+ public final void addKeyListener(KeyListener l) {
addKeyListener(-1, l);
}
- public void addKeyListener(int index, KeyListener l) {
+ @Override
+ public final void addKeyListener(int index, KeyListener l) {
if(l == null) {
return;
}
@SuppressWarnings("unchecked")
ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
- if(0>index) {
+ if(0>index) {
index = clonedListeners.size();
}
clonedListeners.add(index, l);
keyListeners = clonedListeners;
}
- public void removeKeyListener(KeyListener l) {
+ @Override
+ public final void removeKeyListener(KeyListener l) {
if (l == null) {
return;
}
@@ -2205,16 +3394,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
keyListeners = clonedListeners;
}
- public KeyListener getKeyListener(int index) {
+ @Override
+ public final KeyListener getKeyListener(int index) {
@SuppressWarnings("unchecked")
ArrayList<KeyListener> clonedListeners = (ArrayList<KeyListener>) keyListeners.clone();
- if(0>index) {
+ if(0>index) {
index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public KeyListener[] getKeyListeners() {
+ @Override
+ public final KeyListener[] getKeyListeners() {
return keyListeners.toArray(new KeyListener[keyListeners.size()]);
}
@@ -2226,49 +3417,51 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
case KeyEvent.EVENT_KEY_RELEASED:
l.keyReleased(e);
break;
- case KeyEvent.EVENT_KEY_TYPED:
- l.keyTyped(e);
- break;
default:
throw new NativeWindowException("Unexpected key event type " + e.getEventType());
}
- return InputEvent.consumedTag == e.getAttachment();
+ return e.isConsumed();
}
-
+
protected void consumeKeyEvent(KeyEvent e) {
- boolean consumed;
- if(null != keyboardFocusHandler) {
- consumed = propagateKeyEvent(e, keyboardFocusHandler);
+ boolean consumedE = false;
+ if( null != keyboardFocusHandler && !e.isAutoRepeat() ) {
+ consumedE = propagateKeyEvent(e, keyboardFocusHandler);
if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+e+", keyboardFocusHandler consumed: "+consumed);
+ if( consumedE ) {
+ System.err.println("consumeKeyEvent(kfh): "+e+", consumed: "+consumedE);
+ }
+ }
+ }
+ if( !consumedE ) {
+ for(int i = 0; !consumedE && i < keyListeners.size(); i++ ) {
+ consumedE = propagateKeyEvent(e, keyListeners.get(i));
}
- } else {
- consumed = false;
if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+e);
+ System.err.println("consumeKeyEvent(usr): "+e+", consumed: "+consumedE);
}
}
- for(int i = 0; !consumed && i < keyListeners.size(); i++ ) {
- consumed = propagateKeyEvent(e, keyListeners.get(i));
- }
}
//
// WindowListener/Event Support
//
- public void sendWindowEvent(int eventType) {
- consumeWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) );
+ @Override
+ public final void sendWindowEvent(int eventType) {
+ consumeWindowEvent( new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
- public void enqueueWindowEvent(boolean wait, int eventType) {
- enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) );
+ public final void enqueueWindowEvent(boolean wait, int eventType) {
+ enqueueEvent( wait, new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
- public void addWindowListener(WindowListener l) {
+ @Override
+ public final void addWindowListener(WindowListener l) {
addWindowListener(-1, l);
}
- public void addWindowListener(int index, WindowListener l)
+ @Override
+ public final void addWindowListener(int index, WindowListener l)
throws IndexOutOfBoundsException
{
if(l == null) {
@@ -2276,13 +3469,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
@SuppressWarnings("unchecked")
ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
- if(0>index) {
- index = clonedListeners.size();
+ if(0>index) {
+ index = clonedListeners.size();
}
clonedListeners.add(index, l);
windowListeners = clonedListeners;
}
+ @Override
public final void removeWindowListener(WindowListener l) {
if (l == null) {
return;
@@ -2293,16 +3487,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
windowListeners = clonedListeners;
}
- public WindowListener getWindowListener(int index) {
+ @Override
+ public final WindowListener getWindowListener(int index) {
@SuppressWarnings("unchecked")
ArrayList<WindowListener> clonedListeners = (ArrayList<WindowListener>) windowListeners.clone();
- if(0>index) {
- index = clonedListeners.size()-1;
+ if(0>index) {
+ index = clonedListeners.size()-1;
}
return clonedListeners.get(index);
}
- public WindowListener[] getWindowListeners() {
+ @Override
+ public final WindowListener[] getWindowListeners() {
return windowListeners.toArray(new WindowListener[windowListeners.size()]);
}
@@ -2310,7 +3506,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(DEBUG_IMPLEMENTATION) {
System.err.println("consumeWindowEvent: "+e+", visible "+isVisible()+" "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
}
- for(int i = 0; i < windowListeners.size(); i++ ) {
+ for(int i = 0; !e.isConsumed() && i < windowListeners.size(); i++ ) {
WindowListener l = windowListeners.get(i);
switch(e.getEventType()) {
case WindowEvent.EVENT_WINDOW_RESIZED:
@@ -2335,7 +3531,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
l.windowRepaint((WindowUpdateEvent)e);
break;
default:
- throw
+ throw
new NativeWindowException("Unexpected window event type "
+ e.getEventType());
}
@@ -2349,17 +3545,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println("Window.focusChanged: ("+getThreadName()+"): (defer: "+defer+") "+this.hasFocus+" -> "+focusGained+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
}
hasFocus = focusGained;
- final int evt = focusGained ? WindowEvent.EVENT_WINDOW_GAINED_FOCUS : WindowEvent.EVENT_WINDOW_LOST_FOCUS ;
+ final int evt = focusGained ? WindowEvent.EVENT_WINDOW_GAINED_FOCUS : WindowEvent.EVENT_WINDOW_LOST_FOCUS ;
if(!defer) {
sendWindowEvent(evt);
} else {
enqueueWindowEvent(false, evt);
}
}
- }
+ }
/** Triggered by implementation's WM events to update the visibility state. */
- protected void visibleChanged(boolean defer, boolean visible) {
+ protected final void visibleChanged(boolean defer, boolean visible) {
if(this.visible != visible) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.visibleChanged ("+getThreadName()+"): (defer: "+defer+") "+this.visible+" -> "+visible+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -2368,28 +3564,37 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
- private boolean waitForVisible(boolean visible, boolean failFast) {
+ /** Returns -1 if failed, otherwise remaining time until {@link #TIMEOUT_NATIVEWINDOW}, maybe zero. */
+ private long waitForVisible(boolean visible, boolean failFast) {
return waitForVisible(visible, failFast, TIMEOUT_NATIVEWINDOW);
}
- private boolean waitForVisible(boolean visible, boolean failFast, long timeOut) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- for(long sleep = timeOut; 0<sleep && this.visible != visible; sleep-=10 ) {
- display.dispatchMessagesNative(); // status up2date
+ /** Returns -1 if failed, otherwise remaining time until <code>timeOut</code>, maybe zero. */
+ private long waitForVisible(boolean visible, boolean failFast, long timeOut) {
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ long remaining;
+ for(remaining = timeOut; 0<remaining && this.visible != visible; remaining-=10 ) {
try { Thread.sleep(10); } catch (InterruptedException ie) {}
+ display.dispatchMessagesNative(); // status up2date
}
if(this.visible != visible) {
- final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible;
+ final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+this.visible;
if(failFast) {
throw new NativeWindowException(msg);
} else if (DEBUG_IMPLEMENTATION) {
System.err.println(msg);
+ Thread.dumpStack();
}
+ return -1;
+ } else if( 0 < remaining ){
+ return remaining;
+ } else {
+ return 0;
}
- return this.visible == visible;
}
- /** Triggered by implementation's WM events to update the client-area size w/o insets/decorations. */
+ /** Triggered by implementation's WM events to update the client-area size w/o insets/decorations. */
protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
if(force || getWidth() != newWidth || getHeight() != newHeight) {
if(DEBUG_IMPLEMENTATION) {
@@ -2408,20 +3613,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
-
+
private boolean waitForSize(int w, int h, boolean failFast, long timeOut) {
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
- boolean reached = false;
- for(long sleep = timeOut; !reached && 0<sleep; sleep-=10 ) {
- if( w==getWidth() && h==getHeight() ) {
- // reached pos/size
- reached = true;
- } else {
- display.dispatchMessagesNative(); // status up2date
- try { Thread.sleep(10); } catch (InterruptedException ie) {}
- }
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ display.dispatchMessagesNative(); // status up2date
+ long sleep;
+ for(sleep = timeOut; 0<sleep && w!=getWidth() && h!=getHeight(); sleep-=10 ) {
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
+ display.dispatchMessagesNative(); // status up2date
}
- if(!reached) {
+ if(0 >= sleep) {
final String msg = "Size/Pos not reached as requested within "+timeOut+"ms : requested "+w+"x"+h+", is "+getWidth()+"x"+getHeight();
if(failFast) {
throw new NativeWindowException(msg);
@@ -2429,12 +3630,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
System.err.println(msg);
Thread.dumpStack();
}
+ return false;
+ } else {
+ return true;
}
- return reached;
}
-
- /** Triggered by implementation's WM events to update the position. */
- protected void positionChanged(boolean defer, int newX, int newY) {
+
+ /** Triggered by implementation's WM events to update the position. */
+ protected final void positionChanged(boolean defer, int newX, int newY) {
if ( getX() != newX || getY() != newY ) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.positionChanged: ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
@@ -2446,74 +3649,133 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED);
}
} else {
- autoPosition = false; // ensure it's off even w/ same position
+ autoPosition = false; // ensure it's off even w/ same position
}
}
/**
- * Triggered by implementation's WM events to update the insets.
- *
+ * Wait until position is reached within tolerances, either auto-position or custom position.
+ * <p>
+ * Since WM may not obey our positional request exactly, we allow a tolerance of 2 times insets[left/top], or 64 pixels, whatever is greater.
+ * </p>
+ */
+ private boolean waitForPosition(boolean useCustomPosition, int x, int y, long timeOut) {
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final int maxDX, maxDY;
+ {
+ final InsetsImmutable insets = getInsets();
+ maxDX = Math.max(64, insets.getLeftWidth() * 2);
+ maxDY = Math.max(64, insets.getTopHeight() * 2);
+ }
+ long remaining = timeOut;
+ boolean ok;
+ do {
+ if( useCustomPosition ) {
+ ok = Math.abs(x - getX()) <= maxDX && Math.abs(y - getY()) <= maxDY ;
+ } else {
+ ok = !autoPosition;
+ }
+ if( !ok ) {
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
+ display.dispatchMessagesNative(); // status up2date
+ remaining-=10;
+ }
+ } while ( 0<remaining && !ok );
+ if (DEBUG_IMPLEMENTATION) {
+ if( !ok ) {
+ if( useCustomPosition ) {
+ System.err.println("Custom position "+x+"/"+y+" not reached within timeout, has "+getX()+"/"+getY()+", remaining "+remaining);
+ } else {
+ System.err.println("Auto position not reached within timeout, has "+getX()+"/"+getY()+", autoPosition "+autoPosition+", remaining "+remaining);
+ }
+ Thread.dumpStack();
+ }
+ }
+ return ok;
+ }
+
+ /**
+ * Triggered by implementation's WM events to update the insets.
+ *
* @see #getInsets()
* @see #updateInsetsImpl(Insets)
*/
protected void insetsChanged(boolean defer, int left, int right, int top, int bottom) {
if ( left >= 0 && right >= 0 && top >= 0 && bottom >= 0 ) {
- if(isUndecorated()) {
+ if( blockInsetsChange || isUndecorated() ) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.insetsChanged: skip insets change for undecoration mode");
+ System.err.println("Window.insetsChanged (defer: "+defer+"): Skip insets change "+insets+" -> "+new Insets(left, right, top, bottom)+" (blocked "+blockInsetsChange+", undecoration "+isUndecorated()+")");
}
- } else if ( (left != insets.getLeftWidth() || right != insets.getRightWidth() ||
+ } else if ( (left != insets.getLeftWidth() || right != insets.getRightWidth() ||
top != insets.getTopHeight() || bottom != insets.getBottomHeight() )
) {
- insets.setLeftWidth(left);
- insets.setRightWidth(right);
- insets.setTopHeight(top);
- insets.setBottomHeight(bottom);
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.insetsChanged: (defer: "+defer+") "+insets);
+ System.err.println("Window.insetsChanged (defer: "+defer+"): Changed "+insets+" -> "+new Insets(left, right, top, bottom));
}
+ insets.set(left, right, top, bottom);
}
}
}
-
+
/**
- * Triggered by implementation's WM events or programmatically
- *
+ * Triggered by implementation's WM events or programmatic while respecting {@link #getDefaultCloseOperation()}.
+ *
* @param force if true, overrides {@link #setDefaultCloseOperation(WindowClosingMode)} with {@link WindowClosingProtocol#DISPOSE_ON_CLOSE}
* and hence force destruction. Otherwise is follows the user settings.
* @return true if this window is no more valid and hence has been destroyed, otherwise false.
*/
- protected boolean windowDestroyNotify(boolean force) {
+ public final boolean windowDestroyNotify(boolean force) {
+ final WindowClosingMode defMode = getDefaultCloseOperation();
+ final WindowClosingMode mode = force ? WindowClosingMode.DISPOSE_ON_CLOSE : defMode;
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyNotify(force: "+force+") START "+getThreadName()+": "+this);
- }
- if(force) {
- setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
+ System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+defMode+" -> "+mode+") "+getThreadName()+": "+this);
+ // Thread.dumpStack();
}
- // send synced destroy notifications
- enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ final boolean destroyed;
- if(handleDestroyNotify && WindowClosingMode.DISPOSE_ON_CLOSE == getDefaultCloseOperation()) {
- destroy();
+ if( isNativeValid() ) {
+ if( WindowClosingMode.DISPOSE_ON_CLOSE == mode ) {
+ if(force) {
+ setDefaultCloseOperation(mode);
+ }
+ try {
+ if( null == windowDestroyNotifyAction ) {
+ destroy();
+ } else {
+ windowDestroyNotifyAction.run();
+ }
+ } finally {
+ if(force) {
+ setDefaultCloseOperation(defMode);
+ }
+ }
+ } else {
+ // send synced destroy notifications
+ sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ }
+
+ destroyed = !isNativeValid();
+ } else {
+ destroyed = true;
}
-
- final boolean destroyed = !isNativeValid();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.windowDestroyNotify(force: "+force+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
+ System.err.println("Window.windowDestroyNotify(isNativeValid: "+isNativeValid()+", force: "+force+", mode "+mode+") END "+getThreadName()+": destroyed "+destroyed+", "+this);
}
+
return destroyed;
}
- public void windowRepaint(int x, int y, int width, int height) {
- windowRepaint(false, x, y, width, height);
+ @Override
+ public final void windowRepaint(int x, int y, int width, int height) {
+ windowRepaint(false, x, y, width, height);
}
-
+
/**
* Triggered by implementation's WM events to update the content
- */
- protected void windowRepaint(boolean defer, int x, int y, int width, int height) {
+ */
+ protected final void windowRepaint(boolean defer, int x, int y, int width, int height) {
width = ( 0 >= width ) ? getWidth() : width;
height = ( 0 >= height ) ? getHeight() : height;
if(DEBUG_IMPLEMENTATION) {
@@ -2574,10 +3836,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return sb.toString();
}
- protected final void shouldNotCallThis() {
- throw new NativeWindowException("Should not call this");
- }
-
public static String getThreadName() {
return Display.getThreadName();
}
diff --git a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
index 861a6d6be..2ba5b3460 100644
--- a/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
+++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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.awt;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -76,12 +76,12 @@ public class NewtFactoryAWT extends NewtFactory {
}
return (JAWTWindow)nw;
}
-
+
public static void destroyNativeWindow(JAWTWindow jawtWindow) {
final AbstractGraphicsConfiguration config = jawtWindow.getGraphicsConfiguration();
jawtWindow.destroy();
- config.getScreen().getDevice().close();
+ config.getScreen().getDevice().close();
}
-
+
}
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
index cb70da13f..0ee3cc0cd 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTNewtEventFactory.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,138 +20,641 @@
* 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.awt.event;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+/**
+ *
+ * <a name="AWTEventModifierMapping"><h5>AWT Event Modifier Mapping</h5></a>
+ * <pre>
+ Modifier AWT Constant AWT Bit AWT Ex NEWT Constant NEWT Bit
+ ------------- ------------------------------- ------- ------ ------------------------- --------
+ Shift Event.SHIFT_MASK 0
+ Ctrl Event.CTRL_MASK 1
+ Meta Event.META_MASK 2
+ Alt Event.ALT_MASK 3
+ Button1 InputEvent.BUTTON1_MASK 4
+ Button2 InputEvent.BUTTON2_MASK 3
+ Button3 InputEvent.BUTTON3_MASK 2
+ Shift Down InputEvent.SHIFT_DOWN_MASK 6 * InputEvent.SHIFT_MASK 0
+ Ctrl Down InputEvent.CTRL_DOWN_MASK 7 * InputEvent.CTRL_MASK 1
+ Meta Down InputEvent.META_DOWN_MASK 8 * InputEvent.META_MASK 2
+ Alt Down InputEvent.ALT_DOWN_MASK 9 * InputEvent.ALT_MASK 3
+ Button1 Down InputEvent.BUTTON1_DOWN_MASK 10 * InputEvent.BUTTON1_MASK 5
+ Button2 Down InputEvent.BUTTON2_DOWN_MASK 11 * InputEvent.BUTTON2_MASK 6
+ Button3 Down InputEvent.BUTTON3_DOWN_MASK 12 * InputEvent.BUTTON3_MASK 7
+ AltGraph Down InputEvent.ALT_GRAPH_DOWN_MASK 13 * InputEvent.ALT_GRAPH_MASK 4
+ Button4 Down -- 14 * InputEvent.BUTTON4_MASK 8
+ Button5 Down -- 15 * InputEvent.BUTTON5_MASK 9
+ Button6 Down -- 16 * InputEvent.BUTTON6_MASK 10
+ Button7 Down -- 17 * InputEvent.BUTTON7_MASK 11
+ Button8 Down -- 18 * InputEvent.BUTTON8_MASK 12
+ Button9 Down -- 19 * InputEvent.BUTTON9_MASK 13
+ Button10 Down -- 20 * 14
+ Button11 Down -- 21 * 15
+ Button12 Down -- 22 * 16
+ Button13 Down -- 23 * 17
+ Button14 Down -- 24 * 18
+ Button15 Down -- 25 * 19
+ Button16 Down -- 26 * InputEvent.BUTTONLAST_MASK 20
+ Button17 Down -- 27 *
+ Button18 Down -- 28 *
+ Button19 Down -- 29 *
+ Button20 Down -- 30 *
+ Autorepeat -- - InputEvent.AUTOREPEAT_MASK 29
+ Confined -- - InputEvent.CONFINED_MASK 30
+ Invisible -- - InputEvent.INVISIBLE_MASK 31
+ * </pre>
+ *
+ */
public class AWTNewtEventFactory {
- protected static final IntIntHashMap eventTypeAWT2NEWT;
+ /** zero-based AWT button mask array filled by {@link #getAWTButtonDownMask(int)}, allowing fast lookup. */
+ private static int awtButtonDownMasks[] ;
static {
- IntIntHashMap map = new IntIntHashMap();
- map.setKeyNotFoundValue(0xFFFFFFFF);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_OPENED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED);
- map.put(java.awt.event.WindowEvent.WINDOW_CLOSING, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- map.put(java.awt.event.WindowEvent.WINDOW_CLOSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_ICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED);
- map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.FocusEvent.FOCUS_GAINED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_DEACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- map.put(java.awt.event.WindowEvent.WINDOW_LOST_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- map.put(java.awt.event.FocusEvent.FOCUS_LOST, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS);
- // n/a map.put(java.awt.event.WindowEvent.WINDOW_STATE_CHANGED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED);
-
- map.put(java.awt.event.ComponentEvent.COMPONENT_MOVED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED);
- map.put(java.awt.event.ComponentEvent.COMPONENT_RESIZED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED);
- // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_SHOWN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN);
- // n/a map.put(java.awt.event.ComponentEvent.COMPONENT_HIDDEN, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN);
-
- map.put(java.awt.event.MouseEvent.MOUSE_CLICKED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED);
- map.put(java.awt.event.MouseEvent.MOUSE_PRESSED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(java.awt.event.MouseEvent.MOUSE_RELEASED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(java.awt.event.MouseEvent.MOUSE_MOVED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
- map.put(java.awt.event.MouseEvent.MOUSE_ENTERED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED);
- map.put(java.awt.event.MouseEvent.MOUSE_EXITED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED);
- map.put(java.awt.event.MouseEvent.MOUSE_DRAGGED, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
- map.put(java.awt.event.MouseEvent.MOUSE_WHEEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED);
-
- map.put(java.awt.event.KeyEvent.KEY_PRESSED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED);
- map.put(java.awt.event.KeyEvent.KEY_RELEASED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED);
- map.put(java.awt.event.KeyEvent.KEY_TYPED, com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED);
-
- eventTypeAWT2NEWT = map;
+ // There is an assumption in awtModifiers2Newt(int,int,boolean)
+ // that the awtButtonMasks and newtButtonMasks are peers, i.e.
+ // a given index refers to the same button in each array.
+
+ /* {
+ Method _getMaskForButtonMethod = null;
+ try {
+ _getMaskForButtonMethod = ReflectionUtil.getMethod(java.awt.event.InputEvent.class, "getMaskForButton", int.class);
+ } catch(Throwable t) {}
+ getMaskForButtonMethod = _getMaskForButtonMethod;
+ } */
+
+ awtButtonDownMasks = new int[com.jogamp.newt.event.MouseEvent.BUTTON_COUNT] ; // java.awt.MouseInfo.getNumberOfButtons() ;
+ for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+ awtButtonDownMasks[n] = getAWTButtonDownMaskImpl(n+1);
+ }
}
- public static final int awtModifiers2Newt(int awtMods, boolean mouseHint) {
+ public static final short eventTypeAWT2NEWT(int awtType) {
+ switch( awtType ) {
+ // n/a case java.awt.event.WindowEvent.WINDOW_OPENED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_OPENED;
+ case java.awt.event.WindowEvent.WINDOW_CLOSING: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY;
+ case java.awt.event.WindowEvent.WINDOW_CLOSED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DESTROYED;
+ // n/a case java.awt.event.WindowEvent.WINDOW_ICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_ICONIFIED;
+ // n/a case java.awt.event.WindowEvent.WINDOW_DEICONIFIED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED;
+ case java.awt.event.WindowEvent.WINDOW_ACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.FocusEvent.FOCUS_GAINED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_DEACTIVATED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ case java.awt.event.WindowEvent.WINDOW_LOST_FOCUS: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ case java.awt.event.FocusEvent.FOCUS_LOST: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS;
+ // n/a case java.awt.event.WindowEvent.WINDOW_STATE_CHANGED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED;
+
+ case java.awt.event.ComponentEvent.COMPONENT_MOVED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED;
+ case java.awt.event.ComponentEvent.COMPONENT_RESIZED: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_RESIZED;
+ // n/a case java.awt.event.ComponentEvent.COMPONENT_SHOWN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_SHOWN;
+ // n/a case java.awt.event.ComponentEvent.COMPONENT_HIDDEN: return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_HIDDEN;
+
+ case java.awt.event.MouseEvent.MOUSE_CLICKED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+ case java.awt.event.MouseEvent.MOUSE_PRESSED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case java.awt.event.MouseEvent.MOUSE_RELEASED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case java.awt.event.MouseEvent.MOUSE_MOVED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ case java.awt.event.MouseEvent.MOUSE_ENTERED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+ case java.awt.event.MouseEvent.MOUSE_EXITED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+ case java.awt.event.MouseEvent.MOUSE_DRAGGED: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case java.awt.event.MouseEvent.MOUSE_WHEEL: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+
+ case java.awt.event.KeyEvent.KEY_PRESSED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case java.awt.event.KeyEvent.KEY_RELEASED: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
+ }
+
+ private static int getAWTButtonDownMaskImpl(int button) {
+ /**
+ * java.awt.event.InputEvent.getMaskForButton(button);
+ *
+ if(null != getMaskForButtonMethod) {
+ Object r=null;
+ try {
+ r = getMaskForButtonMethod.invoke(null, new Integer(button));
+ } catch (Throwable t) { }
+ if(null != r) {
+ return ((Integer)r).intValue();
+ }
+ } */
+ final int m;
+ switch(button) {
+ case 0 : m = 0; break;
+ case 1 : m = java.awt.event.InputEvent.BUTTON1_DOWN_MASK; break; // 1<<10
+ case 2 : m = java.awt.event.InputEvent.BUTTON2_DOWN_MASK; break; // 1<<11
+ case 3 : m = java.awt.event.InputEvent.BUTTON3_DOWN_MASK; break; // 1<<12
+ default:
+ if( button <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ m = 1 << ( 10 + button ) ; // b4 = 1<<14, b5 = 1<<15, etc
+ } else {
+ m = 0;
+ }
+ }
+ return m;
+ }
+
+ /**
+ * <p>
+ * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+ * </p>
+ *
+ * @param button
+ * @return
+ */
+ public static int getAWTButtonDownMask(int button) {
+ if( 0 < button && button <= awtButtonDownMasks.length ) {
+ return awtButtonDownMasks[button-1];
+ } else {
+ return 0;
+ }
+ }
+
+ public static final short awtButton2Newt(int awtButton) {
+ if( 0 < awtButton && awtButton <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ return (short)awtButton;
+ } else {
+ return (short)0;
+ }
+ }
+
+ /**
+ * Converts the specified set of AWT event modifiers and extended event
+ * modifiers to the equivalent NEWT event modifiers.
+ *
+ * <p>
+ * See <a href="#AWTEventModifierMapping"> AWT event modifier mapping details</a>.
+ * </p>
+ *
+ * @param awtMods
+ * The AWT event modifiers.
+ *
+ * @param awtModsEx
+ * The AWT extended event modifiers.
+ * AWT passes mouse button specific bits here and are the preferred way check the mouse button state.
+ */
+ public static final int awtModifiers2Newt(final int awtMods, final int awtModsEx) {
int newtMods = 0;
+
+ /** Redundant old modifiers ..
if ((awtMods & java.awt.event.InputEvent.SHIFT_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
if ((awtMods & java.awt.event.InputEvent.CTRL_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
if ((awtMods & java.awt.event.InputEvent.META_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
if ((awtMods & java.awt.event.InputEvent.ALT_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
- if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+ if ((awtMods & java.awt.event.InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK; */
+
+ if ((awtModsEx & java.awt.event.InputEvent.SHIFT_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.CTRL_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.META_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.ALT_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+ if ((awtModsEx & java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_GRAPH_MASK;
+
+ // The BUTTON1_MASK, BUTTON2_MASK, and BUTTON3_MASK bits are
+ // being ignored intentionally. The AWT docs say that the
+ // BUTTON1_DOWN_MASK etc bits in the extended modifiers are
+ // the preferred place to check current button state.
+
+ if( 0 != awtModsEx ) {
+ for (int n = 0 ; n < awtButtonDownMasks.length ; ++n) {
+ if ( (awtModsEx & awtButtonDownMasks[n]) != 0 ) {
+ newtMods |= com.jogamp.newt.event.InputEvent.getButtonMask(n+1);
+ }
+ }
+ }
+
return newtMods;
}
- public static final int awtButton2Newt(int awtButton) {
- switch (awtButton) {
- case java.awt.event.MouseEvent.BUTTON1: return com.jogamp.newt.event.MouseEvent.BUTTON1;
- case java.awt.event.MouseEvent.BUTTON2: return com.jogamp.newt.event.MouseEvent.BUTTON2;
- case java.awt.event.MouseEvent.BUTTON3: return com.jogamp.newt.event.MouseEvent.BUTTON3;
+ public static short awtKeyCode2NewtKeyCode(final int awtKeyCode) {
+ final short defNEWTKeyCode = (short)awtKeyCode;
+ switch (awtKeyCode) {
+ case java.awt.event.KeyEvent.VK_HOME : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ case java.awt.event.KeyEvent.VK_END : return com.jogamp.newt.event.KeyEvent.VK_END;
+ case java.awt.event.KeyEvent.VK_FINAL : return com.jogamp.newt.event.KeyEvent.VK_FINAL;
+ case java.awt.event.KeyEvent.VK_PRINTSCREEN : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+ case java.awt.event.KeyEvent.VK_BACK_SPACE : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+ case java.awt.event.KeyEvent.VK_TAB : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+ case java.awt.event.KeyEvent.VK_ENTER : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+ case java.awt.event.KeyEvent.VK_PAGE_DOWN : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+ case java.awt.event.KeyEvent.VK_CLEAR : return com.jogamp.newt.event.KeyEvent.VK_CLEAR;
+ case java.awt.event.KeyEvent.VK_SHIFT : return com.jogamp.newt.event.KeyEvent.VK_SHIFT;
+ case java.awt.event.KeyEvent.VK_PAGE_UP : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+ case java.awt.event.KeyEvent.VK_CONTROL : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+ case java.awt.event.KeyEvent.VK_ALT : return com.jogamp.newt.event.KeyEvent.VK_ALT;
+ case java.awt.event.KeyEvent.VK_ALT_GRAPH : return com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH;
+ case java.awt.event.KeyEvent.VK_CAPS_LOCK : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+ case java.awt.event.KeyEvent.VK_PAUSE : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+ case java.awt.event.KeyEvent.VK_SCROLL_LOCK : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+ case java.awt.event.KeyEvent.VK_CANCEL : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+ case java.awt.event.KeyEvent.VK_INSERT : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+ case java.awt.event.KeyEvent.VK_ESCAPE : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ case java.awt.event.KeyEvent.VK_CONVERT : return com.jogamp.newt.event.KeyEvent.VK_CONVERT;
+ case java.awt.event.KeyEvent.VK_NONCONVERT : return com.jogamp.newt.event.KeyEvent.VK_NONCONVERT;
+ case java.awt.event.KeyEvent.VK_ACCEPT : return com.jogamp.newt.event.KeyEvent.VK_ACCEPT;
+ case java.awt.event.KeyEvent.VK_MODECHANGE : return com.jogamp.newt.event.KeyEvent.VK_MODECHANGE;
+ case java.awt.event.KeyEvent.VK_SPACE : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+ case java.awt.event.KeyEvent.VK_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK;
+ case java.awt.event.KeyEvent.VK_QUOTEDBL : return com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL;
+ case java.awt.event.KeyEvent.VK_NUMBER_SIGN : return com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN;
+ case java.awt.event.KeyEvent.VK_DOLLAR : return com.jogamp.newt.event.KeyEvent.VK_DOLLAR;
+ // case 0x25 : return com.jogamp.newt.event.KeyEvent.VK_PERCENT;
+ case java.awt.event.KeyEvent.VK_AMPERSAND : return com.jogamp.newt.event.KeyEvent.VK_AMPERSAND;
+ case java.awt.event.KeyEvent.VK_QUOTE : return com.jogamp.newt.event.KeyEvent.VK_QUOTE;
+ case java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS : return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+ case java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+ case java.awt.event.KeyEvent.VK_ASTERISK : return com.jogamp.newt.event.KeyEvent.VK_ASTERISK;
+ case java.awt.event.KeyEvent.VK_PLUS : return com.jogamp.newt.event.KeyEvent.VK_PLUS;
+ case java.awt.event.KeyEvent.VK_COMMA : return com.jogamp.newt.event.KeyEvent.VK_COMMA;
+ case java.awt.event.KeyEvent.VK_MINUS : return com.jogamp.newt.event.KeyEvent.VK_MINUS;
+ case java.awt.event.KeyEvent.VK_PERIOD : return com.jogamp.newt.event.KeyEvent.VK_PERIOD;
+ case java.awt.event.KeyEvent.VK_SLASH : return com.jogamp.newt.event.KeyEvent.VK_SLASH;
+ case java.awt.event.KeyEvent.VK_0 : return com.jogamp.newt.event.KeyEvent.VK_0;
+ case java.awt.event.KeyEvent.VK_1 : return com.jogamp.newt.event.KeyEvent.VK_1;
+ case java.awt.event.KeyEvent.VK_2 : return com.jogamp.newt.event.KeyEvent.VK_2;
+ case java.awt.event.KeyEvent.VK_3 : return com.jogamp.newt.event.KeyEvent.VK_3;
+ case java.awt.event.KeyEvent.VK_4 : return com.jogamp.newt.event.KeyEvent.VK_4;
+ case java.awt.event.KeyEvent.VK_5 : return com.jogamp.newt.event.KeyEvent.VK_5;
+ case java.awt.event.KeyEvent.VK_6 : return com.jogamp.newt.event.KeyEvent.VK_6;
+ case java.awt.event.KeyEvent.VK_7 : return com.jogamp.newt.event.KeyEvent.VK_7;
+ case java.awt.event.KeyEvent.VK_8 : return com.jogamp.newt.event.KeyEvent.VK_8;
+ case java.awt.event.KeyEvent.VK_9 : return com.jogamp.newt.event.KeyEvent.VK_9;
+ case java.awt.event.KeyEvent.VK_COLON : return com.jogamp.newt.event.KeyEvent.VK_COLON;
+ case java.awt.event.KeyEvent.VK_SEMICOLON : return com.jogamp.newt.event.KeyEvent.VK_SEMICOLON;
+ case java.awt.event.KeyEvent.VK_LESS : return com.jogamp.newt.event.KeyEvent.VK_LESS;
+ case java.awt.event.KeyEvent.VK_EQUALS : return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
+ case java.awt.event.KeyEvent.VK_GREATER : return com.jogamp.newt.event.KeyEvent.VK_GREATER;
+ case 0x3f : return com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK;
+ case java.awt.event.KeyEvent.VK_AT : return com.jogamp.newt.event.KeyEvent.VK_AT;
+ case java.awt.event.KeyEvent.VK_A : return com.jogamp.newt.event.KeyEvent.VK_A;
+ case java.awt.event.KeyEvent.VK_B : return com.jogamp.newt.event.KeyEvent.VK_B;
+ case java.awt.event.KeyEvent.VK_C : return com.jogamp.newt.event.KeyEvent.VK_C;
+ case java.awt.event.KeyEvent.VK_D : return com.jogamp.newt.event.KeyEvent.VK_D;
+ case java.awt.event.KeyEvent.VK_E : return com.jogamp.newt.event.KeyEvent.VK_E;
+ case java.awt.event.KeyEvent.VK_F : return com.jogamp.newt.event.KeyEvent.VK_F;
+ case java.awt.event.KeyEvent.VK_G : return com.jogamp.newt.event.KeyEvent.VK_G;
+ case java.awt.event.KeyEvent.VK_H : return com.jogamp.newt.event.KeyEvent.VK_H;
+ case java.awt.event.KeyEvent.VK_I : return com.jogamp.newt.event.KeyEvent.VK_I;
+ case java.awt.event.KeyEvent.VK_J : return com.jogamp.newt.event.KeyEvent.VK_J;
+ case java.awt.event.KeyEvent.VK_K : return com.jogamp.newt.event.KeyEvent.VK_K;
+ case java.awt.event.KeyEvent.VK_L : return com.jogamp.newt.event.KeyEvent.VK_L;
+ case java.awt.event.KeyEvent.VK_M : return com.jogamp.newt.event.KeyEvent.VK_M;
+ case java.awt.event.KeyEvent.VK_N : return com.jogamp.newt.event.KeyEvent.VK_N;
+ case java.awt.event.KeyEvent.VK_O : return com.jogamp.newt.event.KeyEvent.VK_O;
+ case java.awt.event.KeyEvent.VK_P : return com.jogamp.newt.event.KeyEvent.VK_P;
+ case java.awt.event.KeyEvent.VK_Q : return com.jogamp.newt.event.KeyEvent.VK_Q;
+ case java.awt.event.KeyEvent.VK_R : return com.jogamp.newt.event.KeyEvent.VK_R;
+ case java.awt.event.KeyEvent.VK_S : return com.jogamp.newt.event.KeyEvent.VK_S;
+ case java.awt.event.KeyEvent.VK_T : return com.jogamp.newt.event.KeyEvent.VK_T;
+ case java.awt.event.KeyEvent.VK_U : return com.jogamp.newt.event.KeyEvent.VK_U;
+ case java.awt.event.KeyEvent.VK_V : return com.jogamp.newt.event.KeyEvent.VK_V;
+ case java.awt.event.KeyEvent.VK_W : return com.jogamp.newt.event.KeyEvent.VK_W;
+ case java.awt.event.KeyEvent.VK_X : return com.jogamp.newt.event.KeyEvent.VK_X;
+ case java.awt.event.KeyEvent.VK_Y : return com.jogamp.newt.event.KeyEvent.VK_Y;
+ case java.awt.event.KeyEvent.VK_Z : return com.jogamp.newt.event.KeyEvent.VK_Z;
+ case java.awt.event.KeyEvent.VK_OPEN_BRACKET : return com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET;
+ case java.awt.event.KeyEvent.VK_BACK_SLASH : return com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH;
+ case java.awt.event.KeyEvent.VK_CLOSE_BRACKET : return com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET;
+ case java.awt.event.KeyEvent.VK_CIRCUMFLEX : return com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX;
+ case java.awt.event.KeyEvent.VK_UNDERSCORE : return com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE;
+ case java.awt.event.KeyEvent.VK_BACK_QUOTE : return com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE;
+ case java.awt.event.KeyEvent.VK_F1 : return com.jogamp.newt.event.KeyEvent.VK_F1;
+ case java.awt.event.KeyEvent.VK_F2 : return com.jogamp.newt.event.KeyEvent.VK_F2;
+ case java.awt.event.KeyEvent.VK_F3 : return com.jogamp.newt.event.KeyEvent.VK_F3;
+ case java.awt.event.KeyEvent.VK_F4 : return com.jogamp.newt.event.KeyEvent.VK_F4;
+ case java.awt.event.KeyEvent.VK_F5 : return com.jogamp.newt.event.KeyEvent.VK_F5;
+ case java.awt.event.KeyEvent.VK_F6 : return com.jogamp.newt.event.KeyEvent.VK_F6;
+ case java.awt.event.KeyEvent.VK_F7 : return com.jogamp.newt.event.KeyEvent.VK_F7;
+ case java.awt.event.KeyEvent.VK_F8 : return com.jogamp.newt.event.KeyEvent.VK_F8;
+ case java.awt.event.KeyEvent.VK_F9 : return com.jogamp.newt.event.KeyEvent.VK_F9;
+ case java.awt.event.KeyEvent.VK_F10 : return com.jogamp.newt.event.KeyEvent.VK_F10;
+ case java.awt.event.KeyEvent.VK_F11 : return com.jogamp.newt.event.KeyEvent.VK_F11;
+ case java.awt.event.KeyEvent.VK_F12 : return com.jogamp.newt.event.KeyEvent.VK_F12;
+ case java.awt.event.KeyEvent.VK_F13 : return com.jogamp.newt.event.KeyEvent.VK_F13;
+ case java.awt.event.KeyEvent.VK_F14 : return com.jogamp.newt.event.KeyEvent.VK_F14;
+ case java.awt.event.KeyEvent.VK_F15 : return com.jogamp.newt.event.KeyEvent.VK_F15;
+ case java.awt.event.KeyEvent.VK_F16 : return com.jogamp.newt.event.KeyEvent.VK_F16;
+ case java.awt.event.KeyEvent.VK_F17 : return com.jogamp.newt.event.KeyEvent.VK_F17;
+ case java.awt.event.KeyEvent.VK_F18 : return com.jogamp.newt.event.KeyEvent.VK_F18;
+ case java.awt.event.KeyEvent.VK_F19 : return com.jogamp.newt.event.KeyEvent.VK_F19;
+ case java.awt.event.KeyEvent.VK_F20 : return com.jogamp.newt.event.KeyEvent.VK_F20;
+ case java.awt.event.KeyEvent.VK_F21 : return com.jogamp.newt.event.KeyEvent.VK_F21;
+ case java.awt.event.KeyEvent.VK_F22 : return com.jogamp.newt.event.KeyEvent.VK_F22;
+ case java.awt.event.KeyEvent.VK_F23 : return com.jogamp.newt.event.KeyEvent.VK_F23;
+ case java.awt.event.KeyEvent.VK_F24 : return com.jogamp.newt.event.KeyEvent.VK_F24;
+ case java.awt.event.KeyEvent.VK_BRACELEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE;
+ case 0x7c : return com.jogamp.newt.event.KeyEvent.VK_PIPE;
+ case java.awt.event.KeyEvent.VK_BRACERIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE;
+ case java.awt.event.KeyEvent.VK_DEAD_TILDE : return com.jogamp.newt.event.KeyEvent.VK_TILDE;
+ case java.awt.event.KeyEvent.VK_DELETE : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case java.awt.event.KeyEvent.VK_NUMPAD0 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+ case java.awt.event.KeyEvent.VK_NUMPAD1 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+ case java.awt.event.KeyEvent.VK_NUMPAD2 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+ case java.awt.event.KeyEvent.VK_NUMPAD3 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+ case java.awt.event.KeyEvent.VK_NUMPAD4 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+ case java.awt.event.KeyEvent.VK_NUMPAD5 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+ case java.awt.event.KeyEvent.VK_NUMPAD6 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+ case java.awt.event.KeyEvent.VK_NUMPAD7 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+ case java.awt.event.KeyEvent.VK_NUMPAD8 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+ case java.awt.event.KeyEvent.VK_NUMPAD9 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+ case java.awt.event.KeyEvent.VK_DECIMAL : return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+ case java.awt.event.KeyEvent.VK_SEPARATOR : return com.jogamp.newt.event.KeyEvent.VK_SEPARATOR;
+ case java.awt.event.KeyEvent.VK_ADD : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+ case java.awt.event.KeyEvent.VK_SUBTRACT : return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+ case java.awt.event.KeyEvent.VK_MULTIPLY : return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+ case java.awt.event.KeyEvent.VK_DIVIDE : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+ case java.awt.event.KeyEvent.VK_NUM_LOCK : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+ case java.awt.event.KeyEvent.VK_KP_LEFT : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_LEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+ case java.awt.event.KeyEvent.VK_KP_UP : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_UP : return com.jogamp.newt.event.KeyEvent.VK_UP;
+ case java.awt.event.KeyEvent.VK_KP_RIGHT : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_RIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+ case java.awt.event.KeyEvent.VK_KP_DOWN : /** Fall through intended .. */
+ case java.awt.event.KeyEvent.VK_DOWN : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+ case java.awt.event.KeyEvent.VK_CONTEXT_MENU : return com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU;
+ case java.awt.event.KeyEvent.VK_WINDOWS : return com.jogamp.newt.event.KeyEvent.VK_WINDOWS;
+ case java.awt.event.KeyEvent.VK_META : return com.jogamp.newt.event.KeyEvent.VK_META;
+ case java.awt.event.KeyEvent.VK_HELP : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+ case java.awt.event.KeyEvent.VK_COMPOSE : return com.jogamp.newt.event.KeyEvent.VK_COMPOSE;
+ case java.awt.event.KeyEvent.VK_BEGIN : return com.jogamp.newt.event.KeyEvent.VK_BEGIN;
+ case java.awt.event.KeyEvent.VK_STOP : return com.jogamp.newt.event.KeyEvent.VK_STOP;
+ case java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ case java.awt.event.KeyEvent.VK_EURO_SIGN : return com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN;
+ case java.awt.event.KeyEvent.VK_CUT : return com.jogamp.newt.event.KeyEvent.VK_CUT;
+ case java.awt.event.KeyEvent.VK_COPY : return com.jogamp.newt.event.KeyEvent.VK_COPY;
+ case java.awt.event.KeyEvent.VK_PASTE : return com.jogamp.newt.event.KeyEvent.VK_PASTE;
+ case java.awt.event.KeyEvent.VK_UNDO : return com.jogamp.newt.event.KeyEvent.VK_UNDO;
+ case java.awt.event.KeyEvent.VK_AGAIN : return com.jogamp.newt.event.KeyEvent.VK_AGAIN;
+ case java.awt.event.KeyEvent.VK_FIND : return com.jogamp.newt.event.KeyEvent.VK_FIND;
+ case java.awt.event.KeyEvent.VK_PROPS : return com.jogamp.newt.event.KeyEvent.VK_PROPS;
+ case java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+ case java.awt.event.KeyEvent.VK_CODE_INPUT : return com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT;
+ case java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS: return com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+ case java.awt.event.KeyEvent.VK_ALL_CANDIDATES: return com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES;
+ case java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+ case java.awt.event.KeyEvent.VK_ALPHANUMERIC : return com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC;
+ case java.awt.event.KeyEvent.VK_KATAKANA : return com.jogamp.newt.event.KeyEvent.VK_KATAKANA;
+ case java.awt.event.KeyEvent.VK_HIRAGANA : return com.jogamp.newt.event.KeyEvent.VK_HIRAGANA;
+ case java.awt.event.KeyEvent.VK_FULL_WIDTH : return com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH;
+ case java.awt.event.KeyEvent.VK_HALF_WIDTH : return com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH;
+ case java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+ case java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+ case java.awt.event.KeyEvent.VK_JAPANESE_ROMAN: return com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN;
+ case java.awt.event.KeyEvent.VK_KANA_LOCK : return com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK;
+ }
+ return defNEWTKeyCode;
+ }
+
+ public static int newtKeyCode2AWTKeyCode(final short newtKeyCode) {
+ final int defAwtKeyCode = 0xFFFF & (int)newtKeyCode;
+ switch (newtKeyCode) {
+ case com.jogamp.newt.event.KeyEvent.VK_HOME : return java.awt.event.KeyEvent.VK_HOME;
+ case com.jogamp.newt.event.KeyEvent.VK_END : return java.awt.event.KeyEvent.VK_END;
+ case com.jogamp.newt.event.KeyEvent.VK_FINAL : return java.awt.event.KeyEvent.VK_FINAL;
+ case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN : return java.awt.event.KeyEvent.VK_PRINTSCREEN;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE : return java.awt.event.KeyEvent.VK_BACK_SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_TAB : return java.awt.event.KeyEvent.VK_TAB;
+ case com.jogamp.newt.event.KeyEvent.VK_ENTER : return java.awt.event.KeyEvent.VK_ENTER;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN : return java.awt.event.KeyEvent.VK_PAGE_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_CLEAR : return java.awt.event.KeyEvent.VK_CLEAR;
+ case com.jogamp.newt.event.KeyEvent.VK_SHIFT : return java.awt.event.KeyEvent.VK_SHIFT;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP : return java.awt.event.KeyEvent.VK_PAGE_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTROL : return java.awt.event.KeyEvent.VK_CONTROL;
+ case com.jogamp.newt.event.KeyEvent.VK_ALT : return java.awt.event.KeyEvent.VK_ALT;
+ // FIXME: On X11 it results to 0xff7e w/ AWTRobot, which is wrong. 0xffea Alt_R is expected AFAIK.
+ case com.jogamp.newt.event.KeyEvent.VK_ALT_GRAPH : return java.awt.event.KeyEvent.VK_ALT_GRAPH;
+ case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK : return java.awt.event.KeyEvent.VK_CAPS_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_PAUSE : return java.awt.event.KeyEvent.VK_PAUSE;
+ case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK : return java.awt.event.KeyEvent.VK_SCROLL_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_CANCEL : return java.awt.event.KeyEvent.VK_CANCEL;
+ case com.jogamp.newt.event.KeyEvent.VK_INSERT : return java.awt.event.KeyEvent.VK_INSERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ESCAPE : return java.awt.event.KeyEvent.VK_ESCAPE;
+ case com.jogamp.newt.event.KeyEvent.VK_CONVERT : return java.awt.event.KeyEvent.VK_CONVERT;
+ case com.jogamp.newt.event.KeyEvent.VK_NONCONVERT : return java.awt.event.KeyEvent.VK_NONCONVERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ACCEPT : return java.awt.event.KeyEvent.VK_ACCEPT;
+ case com.jogamp.newt.event.KeyEvent.VK_MODECHANGE : return java.awt.event.KeyEvent.VK_MODECHANGE;
+ case com.jogamp.newt.event.KeyEvent.VK_SPACE : return java.awt.event.KeyEvent.VK_SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_EXCLAMATION_MARK;
+ case com.jogamp.newt.event.KeyEvent.VK_QUOTEDBL : return java.awt.event.KeyEvent.VK_QUOTEDBL;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMBER_SIGN : return java.awt.event.KeyEvent.VK_NUMBER_SIGN;
+ case com.jogamp.newt.event.KeyEvent.VK_DOLLAR : return java.awt.event.KeyEvent.VK_DOLLAR;
+ case com.jogamp.newt.event.KeyEvent.VK_PERCENT : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_AMPERSAND : return java.awt.event.KeyEvent.VK_AMPERSAND;
+ case com.jogamp.newt.event.KeyEvent.VK_QUOTE : return java.awt.event.KeyEvent.VK_QUOTE;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS : return java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT_PARENTHESIS: return java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS;
+ case com.jogamp.newt.event.KeyEvent.VK_ASTERISK : return java.awt.event.KeyEvent.VK_ASTERISK;
+ case com.jogamp.newt.event.KeyEvent.VK_PLUS : return java.awt.event.KeyEvent.VK_PLUS;
+ case com.jogamp.newt.event.KeyEvent.VK_COMMA : return java.awt.event.KeyEvent.VK_COMMA;
+ case com.jogamp.newt.event.KeyEvent.VK_MINUS : return java.awt.event.KeyEvent.VK_MINUS;
+ case com.jogamp.newt.event.KeyEvent.VK_PERIOD : return java.awt.event.KeyEvent.VK_PERIOD;
+ case com.jogamp.newt.event.KeyEvent.VK_SLASH : return java.awt.event.KeyEvent.VK_SLASH;
+ case com.jogamp.newt.event.KeyEvent.VK_0 : return java.awt.event.KeyEvent.VK_0;
+ case com.jogamp.newt.event.KeyEvent.VK_1 : return java.awt.event.KeyEvent.VK_1;
+ case com.jogamp.newt.event.KeyEvent.VK_2 : return java.awt.event.KeyEvent.VK_2;
+ case com.jogamp.newt.event.KeyEvent.VK_3 : return java.awt.event.KeyEvent.VK_3;
+ case com.jogamp.newt.event.KeyEvent.VK_4 : return java.awt.event.KeyEvent.VK_4;
+ case com.jogamp.newt.event.KeyEvent.VK_5 : return java.awt.event.KeyEvent.VK_5;
+ case com.jogamp.newt.event.KeyEvent.VK_6 : return java.awt.event.KeyEvent.VK_6;
+ case com.jogamp.newt.event.KeyEvent.VK_7 : return java.awt.event.KeyEvent.VK_7;
+ case com.jogamp.newt.event.KeyEvent.VK_8 : return java.awt.event.KeyEvent.VK_8;
+ case com.jogamp.newt.event.KeyEvent.VK_9 : return java.awt.event.KeyEvent.VK_9;
+ case com.jogamp.newt.event.KeyEvent.VK_COLON : return java.awt.event.KeyEvent.VK_COLON;
+ case com.jogamp.newt.event.KeyEvent.VK_SEMICOLON : return java.awt.event.KeyEvent.VK_SEMICOLON;
+ case com.jogamp.newt.event.KeyEvent.VK_LESS : return java.awt.event.KeyEvent.VK_LESS;
+ case com.jogamp.newt.event.KeyEvent.VK_EQUALS : return java.awt.event.KeyEvent.VK_EQUALS;
+ case com.jogamp.newt.event.KeyEvent.VK_GREATER : return java.awt.event.KeyEvent.VK_GREATER;
+ case com.jogamp.newt.event.KeyEvent.VK_QUESTIONMARK : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_AT : return java.awt.event.KeyEvent.VK_AT;
+ case com.jogamp.newt.event.KeyEvent.VK_A : return java.awt.event.KeyEvent.VK_A;
+ case com.jogamp.newt.event.KeyEvent.VK_B : return java.awt.event.KeyEvent.VK_B;
+ case com.jogamp.newt.event.KeyEvent.VK_C : return java.awt.event.KeyEvent.VK_C;
+ case com.jogamp.newt.event.KeyEvent.VK_D : return java.awt.event.KeyEvent.VK_D;
+ case com.jogamp.newt.event.KeyEvent.VK_E : return java.awt.event.KeyEvent.VK_E;
+ case com.jogamp.newt.event.KeyEvent.VK_F : return java.awt.event.KeyEvent.VK_F;
+ case com.jogamp.newt.event.KeyEvent.VK_G : return java.awt.event.KeyEvent.VK_G;
+ case com.jogamp.newt.event.KeyEvent.VK_H : return java.awt.event.KeyEvent.VK_H;
+ case com.jogamp.newt.event.KeyEvent.VK_I : return java.awt.event.KeyEvent.VK_I;
+ case com.jogamp.newt.event.KeyEvent.VK_J : return java.awt.event.KeyEvent.VK_J;
+ case com.jogamp.newt.event.KeyEvent.VK_K : return java.awt.event.KeyEvent.VK_K;
+ case com.jogamp.newt.event.KeyEvent.VK_L : return java.awt.event.KeyEvent.VK_L;
+ case com.jogamp.newt.event.KeyEvent.VK_M : return java.awt.event.KeyEvent.VK_M;
+ case com.jogamp.newt.event.KeyEvent.VK_N : return java.awt.event.KeyEvent.VK_N;
+ case com.jogamp.newt.event.KeyEvent.VK_O : return java.awt.event.KeyEvent.VK_O;
+ case com.jogamp.newt.event.KeyEvent.VK_P : return java.awt.event.KeyEvent.VK_P;
+ case com.jogamp.newt.event.KeyEvent.VK_Q : return java.awt.event.KeyEvent.VK_Q;
+ case com.jogamp.newt.event.KeyEvent.VK_R : return java.awt.event.KeyEvent.VK_R;
+ case com.jogamp.newt.event.KeyEvent.VK_S : return java.awt.event.KeyEvent.VK_S;
+ case com.jogamp.newt.event.KeyEvent.VK_T : return java.awt.event.KeyEvent.VK_T;
+ case com.jogamp.newt.event.KeyEvent.VK_U : return java.awt.event.KeyEvent.VK_U;
+ case com.jogamp.newt.event.KeyEvent.VK_V : return java.awt.event.KeyEvent.VK_V;
+ case com.jogamp.newt.event.KeyEvent.VK_W : return java.awt.event.KeyEvent.VK_W;
+ case com.jogamp.newt.event.KeyEvent.VK_X : return java.awt.event.KeyEvent.VK_X;
+ case com.jogamp.newt.event.KeyEvent.VK_Y : return java.awt.event.KeyEvent.VK_Y;
+ case com.jogamp.newt.event.KeyEvent.VK_Z : return java.awt.event.KeyEvent.VK_Z;
+ case com.jogamp.newt.event.KeyEvent.VK_OPEN_BRACKET : return java.awt.event.KeyEvent.VK_OPEN_BRACKET;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SLASH : return java.awt.event.KeyEvent.VK_BACK_SLASH;
+ case com.jogamp.newt.event.KeyEvent.VK_CLOSE_BRACKET : return java.awt.event.KeyEvent.VK_CLOSE_BRACKET;
+ case com.jogamp.newt.event.KeyEvent.VK_CIRCUMFLEX : return java.awt.event.KeyEvent.VK_CIRCUMFLEX;
+ case com.jogamp.newt.event.KeyEvent.VK_UNDERSCORE : return java.awt.event.KeyEvent.VK_UNDERSCORE;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_QUOTE : return java.awt.event.KeyEvent.VK_BACK_QUOTE;
+ case com.jogamp.newt.event.KeyEvent.VK_F1 : return java.awt.event.KeyEvent.VK_F1;
+ case com.jogamp.newt.event.KeyEvent.VK_F2 : return java.awt.event.KeyEvent.VK_F2;
+ case com.jogamp.newt.event.KeyEvent.VK_F3 : return java.awt.event.KeyEvent.VK_F3;
+ case com.jogamp.newt.event.KeyEvent.VK_F4 : return java.awt.event.KeyEvent.VK_F4;
+ case com.jogamp.newt.event.KeyEvent.VK_F5 : return java.awt.event.KeyEvent.VK_F5;
+ case com.jogamp.newt.event.KeyEvent.VK_F6 : return java.awt.event.KeyEvent.VK_F6;
+ case com.jogamp.newt.event.KeyEvent.VK_F7 : return java.awt.event.KeyEvent.VK_F7;
+ case com.jogamp.newt.event.KeyEvent.VK_F8 : return java.awt.event.KeyEvent.VK_F8;
+ case com.jogamp.newt.event.KeyEvent.VK_F9 : return java.awt.event.KeyEvent.VK_F9;
+ case com.jogamp.newt.event.KeyEvent.VK_F10 : return java.awt.event.KeyEvent.VK_F10;
+ case com.jogamp.newt.event.KeyEvent.VK_F11 : return java.awt.event.KeyEvent.VK_F11;
+ case com.jogamp.newt.event.KeyEvent.VK_F12 : return java.awt.event.KeyEvent.VK_F12;
+ case com.jogamp.newt.event.KeyEvent.VK_F13 : return java.awt.event.KeyEvent.VK_F13;
+ case com.jogamp.newt.event.KeyEvent.VK_F14 : return java.awt.event.KeyEvent.VK_F14;
+ case com.jogamp.newt.event.KeyEvent.VK_F15 : return java.awt.event.KeyEvent.VK_F15;
+ case com.jogamp.newt.event.KeyEvent.VK_F16 : return java.awt.event.KeyEvent.VK_F16;
+ case com.jogamp.newt.event.KeyEvent.VK_F17 : return java.awt.event.KeyEvent.VK_F17;
+ case com.jogamp.newt.event.KeyEvent.VK_F18 : return java.awt.event.KeyEvent.VK_F18;
+ case com.jogamp.newt.event.KeyEvent.VK_F19 : return java.awt.event.KeyEvent.VK_F19;
+ case com.jogamp.newt.event.KeyEvent.VK_F20 : return java.awt.event.KeyEvent.VK_F20;
+ case com.jogamp.newt.event.KeyEvent.VK_F21 : return java.awt.event.KeyEvent.VK_F21;
+ case com.jogamp.newt.event.KeyEvent.VK_F22 : return java.awt.event.KeyEvent.VK_F22;
+ case com.jogamp.newt.event.KeyEvent.VK_F23 : return java.awt.event.KeyEvent.VK_F23;
+ case com.jogamp.newt.event.KeyEvent.VK_F24 : return java.awt.event.KeyEvent.VK_F24;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT_BRACE : return java.awt.event.KeyEvent.VK_BRACELEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_PIPE : return defAwtKeyCode;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT_BRACE : return java.awt.event.KeyEvent.VK_BRACERIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_TILDE : return java.awt.event.KeyEvent.VK_DEAD_TILDE;
+ case com.jogamp.newt.event.KeyEvent.VK_DELETE : return java.awt.event.KeyEvent.VK_DELETE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 : return java.awt.event.KeyEvent.VK_NUMPAD0;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1 : return java.awt.event.KeyEvent.VK_NUMPAD1;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2 : return java.awt.event.KeyEvent.VK_NUMPAD2;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3 : return java.awt.event.KeyEvent.VK_NUMPAD3;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4 : return java.awt.event.KeyEvent.VK_NUMPAD4;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5 : return java.awt.event.KeyEvent.VK_NUMPAD5;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6 : return java.awt.event.KeyEvent.VK_NUMPAD6;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7 : return java.awt.event.KeyEvent.VK_NUMPAD7;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8 : return java.awt.event.KeyEvent.VK_NUMPAD8;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9 : return java.awt.event.KeyEvent.VK_NUMPAD9;
+ case com.jogamp.newt.event.KeyEvent.VK_DECIMAL : return java.awt.event.KeyEvent.VK_DECIMAL;
+ case com.jogamp.newt.event.KeyEvent.VK_SEPARATOR : return java.awt.event.KeyEvent.VK_SEPARATOR;
+ case com.jogamp.newt.event.KeyEvent.VK_ADD : return java.awt.event.KeyEvent.VK_ADD;
+ case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT : return java.awt.event.KeyEvent.VK_SUBTRACT;
+ case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY : return java.awt.event.KeyEvent.VK_MULTIPLY;
+ case com.jogamp.newt.event.KeyEvent.VK_DIVIDE : return java.awt.event.KeyEvent.VK_DIVIDE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK : return java.awt.event.KeyEvent.VK_NUM_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT : return java.awt.event.KeyEvent.VK_LEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_UP : return java.awt.event.KeyEvent.VK_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT : return java.awt.event.KeyEvent.VK_RIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_DOWN : return java.awt.event.KeyEvent.VK_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTEXT_MENU : return java.awt.event.KeyEvent.VK_CONTEXT_MENU;
+ case com.jogamp.newt.event.KeyEvent.VK_WINDOWS : return java.awt.event.KeyEvent.VK_WINDOWS;
+ case com.jogamp.newt.event.KeyEvent.VK_META : return java.awt.event.KeyEvent.VK_META;
+ case com.jogamp.newt.event.KeyEvent.VK_HELP : return java.awt.event.KeyEvent.VK_HELP;
+ case com.jogamp.newt.event.KeyEvent.VK_COMPOSE : return java.awt.event.KeyEvent.VK_COMPOSE;
+ case com.jogamp.newt.event.KeyEvent.VK_BEGIN : return java.awt.event.KeyEvent.VK_BEGIN;
+ case com.jogamp.newt.event.KeyEvent.VK_STOP : return java.awt.event.KeyEvent.VK_STOP;
+ case com.jogamp.newt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK: return java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ case com.jogamp.newt.event.KeyEvent.VK_EURO_SIGN : return java.awt.event.KeyEvent.VK_EURO_SIGN;
+ case com.jogamp.newt.event.KeyEvent.VK_CUT : return java.awt.event.KeyEvent.VK_CUT;
+ case com.jogamp.newt.event.KeyEvent.VK_COPY : return java.awt.event.KeyEvent.VK_COPY;
+ case com.jogamp.newt.event.KeyEvent.VK_PASTE : return java.awt.event.KeyEvent.VK_PASTE;
+ case com.jogamp.newt.event.KeyEvent.VK_UNDO : return java.awt.event.KeyEvent.VK_UNDO;
+ case com.jogamp.newt.event.KeyEvent.VK_AGAIN : return java.awt.event.KeyEvent.VK_AGAIN;
+ case com.jogamp.newt.event.KeyEvent.VK_FIND : return java.awt.event.KeyEvent.VK_FIND;
+ case com.jogamp.newt.event.KeyEvent.VK_PROPS : return java.awt.event.KeyEvent.VK_PROPS;
+ case com.jogamp.newt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF: return java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF;
+ case com.jogamp.newt.event.KeyEvent.VK_CODE_INPUT : return java.awt.event.KeyEvent.VK_CODE_INPUT;
+ case com.jogamp.newt.event.KeyEvent.VK_ROMAN_CHARACTERS: return java.awt.event.KeyEvent.VK_ROMAN_CHARACTERS;
+ case com.jogamp.newt.event.KeyEvent.VK_ALL_CANDIDATES: return java.awt.event.KeyEvent.VK_ALL_CANDIDATES;
+ case com.jogamp.newt.event.KeyEvent.VK_PREVIOUS_CANDIDATE: return java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE;
+ case com.jogamp.newt.event.KeyEvent.VK_ALPHANUMERIC : return java.awt.event.KeyEvent.VK_ALPHANUMERIC;
+ case com.jogamp.newt.event.KeyEvent.VK_KATAKANA : return java.awt.event.KeyEvent.VK_KATAKANA;
+ case com.jogamp.newt.event.KeyEvent.VK_HIRAGANA : return java.awt.event.KeyEvent.VK_HIRAGANA;
+ case com.jogamp.newt.event.KeyEvent.VK_FULL_WIDTH : return java.awt.event.KeyEvent.VK_FULL_WIDTH;
+ case com.jogamp.newt.event.KeyEvent.VK_HALF_WIDTH : return java.awt.event.KeyEvent.VK_HALF_WIDTH;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_KATAKANA: return java.awt.event.KeyEvent.VK_JAPANESE_KATAKANA;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_HIRAGANA: return java.awt.event.KeyEvent.VK_JAPANESE_HIRAGANA;
+ case com.jogamp.newt.event.KeyEvent.VK_JAPANESE_ROMAN: return java.awt.event.KeyEvent.VK_JAPANESE_ROMAN;
+ case com.jogamp.newt.event.KeyEvent.VK_KANA_LOCK : return java.awt.event.KeyEvent.VK_KANA_LOCK;
}
- return 0;
+ return defAwtKeyCode;
}
public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.WindowEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?(Object)event.getComponent():(Object)newtSource), System.currentTimeMillis());
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, ((null==newtSource)?(Object)event.getComponent():(Object)newtSource), System.currentTimeMillis());
}
return null; // no mapping ..
}
public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.ComponentEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
}
return null; // no mapping ..
}
public static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.FocusEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ return new com.jogamp.newt.event.WindowEvent(newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis());
}
return null; // no mapping ..
}
public static final com.jogamp.newt.event.MouseEvent createMouseEvent(java.awt.event.MouseEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- int rotation = 0;
+ final short newtType = eventTypeAWT2NEWT(event.getID());
+ if( (short)0 != newtType ) {
+ float rotation = 0;
if (event instanceof java.awt.event.MouseWheelEvent) {
// AWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
- rotation = -1 * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
+ rotation = -1f * ((java.awt.event.MouseWheelEvent)event).getWheelRotation();
}
- int mods = awtModifiers2Newt(event.getModifiers(), true);
+ final short newtButton = awtButton2Newt(event.getButton());
+ int mods = awtModifiers2Newt(event.getModifiers(), event.getModifiersEx());
+ mods |= com.jogamp.newt.event.InputEvent.getButtonMask(newtButton); // always include NEWT BUTTON_MASK
if(null!=newtSource) {
if(newtSource.isPointerConfined()) {
- mods |= InputEvent.CONFINED_MASK;
+ mods |= com.jogamp.newt.event.InputEvent.CONFINED_MASK;
}
if(!newtSource.isPointerVisible()) {
- mods |= InputEvent.INVISIBLE_MASK;
+ mods |= com.jogamp.newt.event.InputEvent.INVISIBLE_MASK;
}
}
-
return new com.jogamp.newt.event.MouseEvent(
- type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
- mods, event.getX(), event.getY(), event.getClickCount(),
- awtButton2Newt(event.getButton()), rotation);
+ newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
+ mods, event.getX(), event.getY(), (short)event.getClickCount(),
+ newtButton, MouseEvent.getRotationXYZ(rotation, mods), 1f);
}
return null; // no mapping ..
}
public static final com.jogamp.newt.event.KeyEvent createKeyEvent(java.awt.event.KeyEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeAWT2NEWT.get(event.getID());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.KeyEvent(
- type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
- awtModifiers2Newt(event.getModifiers(), false),
- event.getKeyCode(), event.getKeyChar());
+ return createKeyEvent(eventTypeAWT2NEWT(event.getID()), event, newtSource);
+ }
+
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(short newtType, java.awt.event.KeyEvent event, com.jogamp.newt.Window newtSource) {
+ if( (short)0 != newtType ) {
+ final short newtKeyCode = awtKeyCode2NewtKeyCode( event.getKeyCode() );
+ return com.jogamp.newt.event.KeyEvent.create(
+ newtType, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, event.getWhen(),
+ awtModifiers2Newt(event.getModifiers(), event.getModifiersEx()),
+ newtKeyCode, newtKeyCode, event.getKeyChar());
}
return null; // no mapping ..
}
}
-
diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
index ce8ed7c49..770502326 100644
--- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
+++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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.awt.event;
import java.awt.KeyboardFocusManager;
@@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow;
import jogamp.newt.driver.DriverUpdatePosition;
+import com.jogamp.newt.Window;
import com.jogamp.newt.event.awt.AWTAdapter;
import com.jogamp.newt.event.awt.AWTWindowAdapter;
@@ -41,111 +42,147 @@ import com.jogamp.newt.event.awt.AWTWindowAdapter;
* Specialized parent/client adapter,
* where the NEWT child window really gets resized,
* and the parent move window event gets discarded. */
-public class AWTParentWindowAdapter
- extends AWTWindowAdapter
- implements java.awt.event.HierarchyListener
+public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt.event.HierarchyListener
{
NativeWindow downstreamParent;
-
+
public AWTParentWindowAdapter(NativeWindow downstreamParent, com.jogamp.newt.Window downstream) {
super(downstream);
this.downstreamParent = downstreamParent;
}
+ public AWTParentWindowAdapter() {
+ super();
+ }
+ public AWTParentWindowAdapter setDownstream(NativeWindow downstreamParent, com.jogamp.newt.Window downstream) {
+ setDownstream(downstream);
+ this.downstreamParent = downstreamParent;
+ return this;
+ }
+
+ @Override
+ public synchronized AWTAdapter clear() {
+ super.clear();
+ this.downstreamParent = null;
+ return this;
+ }
- public AWTAdapter addTo(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter addTo(java.awt.Component awtComponent) {
awtComponent.addHierarchyListener(this);
return super.addTo(awtComponent);
}
- public AWTAdapter removeFrom(java.awt.Component awtComponent) {
+ @Override
+ public synchronized AWTAdapter removeFrom(java.awt.Component awtComponent) {
awtComponent.removeHierarchyListener(this);
return super.removeFrom(awtComponent);
}
- public void focusGained(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusGained(java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
// forward focus to NEWT child
final com.jogamp.newt.Window newtChild = getNewtWindow();
- final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
- final boolean isParent = downstreamParent == newtChild.getParent();
- final boolean isFullscreen = newtChild.isFullscreen();
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e+", isParent: "+isParent+", isFS "+isFullscreen);
- }
- if(isParent) {
- if(isOnscreen && !isFullscreen) {
- KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ if( null != newtChild ) {
+ final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen();
+ final boolean isParent = downstreamParent == newtChild.getParent();
+ final boolean isFullscreen = newtChild.isFullscreen();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e+", isParent: "+isParent+", isFS "+isFullscreen);
+ }
+ if(isParent) {
+ if(isOnscreen && !isFullscreen) {
+ KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
+ }
+ newtChild.requestFocus(false);
}
- newtChild.requestFocus(false);
}
}
- public void focusLost(java.awt.event.FocusEvent e) {
+ @Override
+ public synchronized void focusLost(java.awt.event.FocusEvent e) {
+ if( !isSetup ) { return; }
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: focusLost: "+ e);
}
}
- public void componentResized(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentResized(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
// Need to resize the NEWT child window
// the resized event will be send via the native window feedback.
final java.awt.Component comp = e.getComponent();
if(DEBUG_IMPLEMENTATION) {
System.err.println("AWT: componentResized: "+comp);
}
- getNewtWindow().runOnEDTIfAvail(false, new Runnable() {
- public void run() {
- int cw = comp.getWidth();
- int ch = comp.getHeight();
- if( 0 < cw * ch ) {
- if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) {
- getNewtWindow().setSize(cw, ch);
- if(comp.isVisible() != getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(comp.isVisible());
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild ) {
+ newtChild.runOnEDTIfAvail(false, new Runnable() {
+ @Override
+ public void run() {
+ final int cw = comp.getWidth();
+ final int ch = comp.getHeight();
+ if( 0 < cw && 0 < ch ) {
+ if( newtChild.getWidth() != cw || newtChild.getHeight() != ch ) {
+ newtChild.setSize(cw, ch);
+ final boolean v = comp.isShowing(); // compute showing-state throughout hierarchy
+ if(v != newtChild.isVisible()) {
+ newtChild.setVisible(v);
+ }
}
+ } else if(newtChild.isVisible()) {
+ newtChild.setVisible(false);
}
- } else if(getNewtWindow().isVisible()) {
- getNewtWindow().setVisible(false);
- }
- }});
+ }});
+ }
}
- public void componentMoved(java.awt.event.ComponentEvent e) {
+ @Override
+ public synchronized void componentMoved(java.awt.event.ComponentEvent e) {
+ if( !isSetup ) { return; }
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: componentMoved: "+e);
+ System.err.println("AWT: componentMoved: "+e);
+ }
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild && ( newtChild.getDelegatedWindow() instanceof DriverUpdatePosition ) ) {
+ ((DriverUpdatePosition)newtChild.getDelegatedWindow()).updatePosition(0, 0);
}
- if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) {
- ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition();
- }
}
- public void windowActivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowActivated(java.awt.event.WindowEvent e) {
// no propagation to NEWT child window
}
- public void windowDeactivated(java.awt.event.WindowEvent e) {
+ @Override
+ public synchronized void windowDeactivated(java.awt.event.WindowEvent e) {
// no propagation to NEWT child window
}
- public void hierarchyChanged(java.awt.event.HierarchyEvent e) {
- if( null == getNewtEventListener() ) {
- long bits = e.getChangeFlags();
- final java.awt.Component changed = e.getChanged();
+ @Override
+ public synchronized void hierarchyChanged(java.awt.event.HierarchyEvent e) {
+ if( !isSetup ) { return; }
+ final Window newtChild = getNewtWindow();
+ if( null != newtChild && null == getNewtEventListener() ) {
+ final long bits = e.getChangeFlags();
+ final java.awt.Component comp = e.getComponent();
if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) {
- final boolean showing = changed.isShowing();
+ final boolean showing = comp.isShowing(); // compute showing-state throughout hierarchy
if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed+", source "+e.getComponent());
+ System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", comp "+comp+", changed "+e.getChanged());
}
- getNewtWindow().runOnEDTIfAvail(false, new Runnable() {
+ newtChild.runOnEDTIfAvail(false, new Runnable() {
+ @Override
public void run() {
- if(getNewtWindow().isVisible() != showing) {
- getNewtWindow().setVisible(showing);
+ if(newtChild.isVisible() != showing) {
+ newtChild.setVisible(showing);
}
}});
- }
+ }
if(DEBUG_IMPLEMENTATION) {
if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) {
- final boolean displayability = changed.isDisplayable();
- System.err.println("AWT: hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed);
+ System.err.println("AWT: hierarchyChanged DISPLAYABILITY_CHANGED: "+e.getChanged());
}
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
index 0a824e83b..0ff86fe93 100644
--- a/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
+++ b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java
@@ -1,10 +1,10 @@
package jogamp.newt.driver;
-/**
+/**
* Interface tagging driver requirement of clearing the focus.
* <p>
- * Some drivers require a programmatic {@link #clearFocus()} when traversing the focus.
- * </p>
+ * Some drivers require a programmatic {@link #clearFocus()} when traversing the focus.
+ * </p>
*/
public interface DriverClearFocus {
/** Programmatic clear the focus */
diff --git a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
index bb846c081..e5f9b6a68 100644
--- a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
+++ b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java
@@ -1,9 +1,15 @@
package jogamp.newt.driver;
-/**
+/**
* Interface tagging driver requirement of absolute positioning, ie. depend on parent position.
*/
public interface DriverUpdatePosition {
- /** Programmatic update the position */
- void updatePosition();
+ /**
+ * Programmatic update the top-left corner
+ * of the client area relative to it's parent.
+ *
+ * @param x x-component
+ * @param y y-component
+ **/
+ void updatePosition(int x, int y);
}
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..967acd413
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
@@ -0,0 +1,80 @@
+/**
+ * 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 jogamp.newt.DisplayImpl;
+
+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 = DisplayImpl.isPNGUtilAvailable() && ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl);
+ }
+
+ /** Returns true if PNG decoder is available. */
+ public static boolean isAvailable() {
+ return avail;
+ }
+
+ /**
+ * Special implementation for X11 Window Icons
+ * <p>
+ * The returned byte buffer is a direct buffer!
+ * </p>
+ *
+ * @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);
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java b/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java
deleted file mode 100644
index e108ed0bb..000000000
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright 2011 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.android;
-
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.util.DisplayMetrics;
-import android.view.Surface;
-import android.view.WindowManager;
-
-public class AndroidScreen extends jogamp.newt.ScreenImpl {
-
- static {
- AndroidDisplay.initSingleton();
- }
-
- public AndroidScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() { }
-
- protected ScreenMode getCurrentScreenModeImpl() {
- final Context ctx = jogamp.common.os.android.StaticContext.getContext();
- final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
- final DisplayMetrics outMetrics = new DisplayMetrics();
- final android.view.Display aDisplay = wmgr.getDefaultDisplay();
- aDisplay.getMetrics(outMetrics);
-
- final int arot = aDisplay.getRotation();
- final int nrot = androidRotation2NewtRotation(arot);
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int offset = 1; // set later for verification of iterator
- offset = getScreenSize(outMetrics, nrot, props, offset);
- offset = getBpp(aDisplay, props, offset);
- offset = getScreenSizeMM(outMetrics, props, offset);
- props[offset++] = (int) aDisplay.getRefreshRate();
- props[offset++] = nrot;
- props[offset - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = offset; // count
- return ScreenModeUtil.streamIn(props, 0);
- }
-
- protected int validateScreenIndex(int idx) {
- return 0; // FIXME: only one screen available ?
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- final ScreenMode sm = getCurrentScreenMode();
- virtualSize.setWidth(sm.getRotatedWidth());
- virtualSize.setHeight(sm.getRotatedHeight());
- }
-
- //----------------------------------------------------------------------
- // Internals only
- //
- static int androidRotation2NewtRotation(int arot) {
- switch(arot) {
- case Surface.ROTATION_270: return ScreenMode.ROTATE_270;
- case Surface.ROTATION_180: return ScreenMode.ROTATE_180;
- case Surface.ROTATION_90: return ScreenMode.ROTATE_90;
- case Surface.ROTATION_0:
- }
- return ScreenMode.ROTATE_0;
- }
- static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) {
- // swap width and height, since Android reflects rotated dimension, we don't
- if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) {
- props[offset++] = outMetrics.heightPixels;
- props[offset++] = outMetrics.widthPixels;
- } else {
- props[offset++] = outMetrics.widthPixels;
- props[offset++] = outMetrics.heightPixels;
- }
- return offset;
- }
- static int getBpp(android.view.Display aDisplay, int[] props, int offset) {
- int bpp;
- switch(aDisplay.getPixelFormat()) {
- case PixelFormat.RGBA_8888: bpp=32; break;
- case PixelFormat.RGBX_8888: bpp=32; break;
- case PixelFormat.RGB_888: bpp=24; break;
- case PixelFormat.RGB_565: bpp=16; break;
- case PixelFormat.RGBA_5551: bpp=16; break;
- case PixelFormat.RGBA_4444: bpp=16; break;
- case PixelFormat.RGB_332: bpp= 8; break;
- default: bpp=32;
- }
- props[offset++] = bpp;
- return offset;
- }
- static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) {
- final float iw = (float) outMetrics.widthPixels / outMetrics.xdpi;
- final float ih = (float) outMetrics.heightPixels / outMetrics.xdpi;
- final float mmpi = 25.4f;
- props[offset++] = (int) ((iw * mmpi)+0.5);
- props[offset++] = (int) ((ih * mmpi)+0.5);
- return offset;
- }
-}
-
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
deleted file mode 100644
index 63d5f7003..000000000
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/**
- * Copyright 2011 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.android;
-
-import jogamp.common.os.android.StaticContext;
-import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
-
-import javax.media.nativewindow.Capabilities;
-import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.VisualIDHolder;
-import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.Point;
-import javax.media.opengl.GLCapabilitiesChooser;
-import javax.media.opengl.GLCapabilitiesImmutable;
-
-import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-
-import jogamp.opengl.egl.EGL;
-import jogamp.opengl.egl.EGLGraphicsConfiguration;
-import jogamp.opengl.egl.EGLGraphicsConfigurationFactory;
-
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceHolder.Callback2;
-import android.view.SurfaceView;
-import android.view.View;
-
-public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 {
- static {
- AndroidDisplay.initSingleton();
- }
-
- public static CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
- PixelFormat pf = new PixelFormat();
- PixelFormat.getPixelFormatInfo(format, pf);
- final CapabilitiesImmutable res;
- int r, g, b, a;
-
- switch(format) {
- case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break;
- case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break;
- case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break;
- case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break;
- case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break;
- case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break;
- case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break;
- default: throw new InternalError("Unhandled pixelformat: "+format);
- }
- final boolean change = matchFormatPrecise ||
- rCaps.getRedBits() > r &&
- rCaps.getGreenBits() > g &&
- rCaps.getBlueBits() > b &&
- rCaps.getAlphaBits() > a ;
-
- if(change) {
- Capabilities nCaps = (Capabilities) rCaps.cloneMutable();
- nCaps.setRedBits(r);
- nCaps.setGreenBits(g);
- nCaps.setBlueBits(b);
- nCaps.setAlphaBits(a);
- res = nCaps;
- } else {
- res = rCaps;
- }
- Log.d(MD.TAG, "fixCaps: format: "+format);
- Log.d(MD.TAG, "fixCaps: requested: "+rCaps);
- Log.d(MD.TAG, "fixCaps: chosen: "+res);
-
- return res;
- }
-
- public static int getFormat(CapabilitiesImmutable rCaps) {
- int fmt = PixelFormat.UNKNOWN;
-
- if(!rCaps.isBackgroundOpaque()) {
- fmt = PixelFormat.TRANSLUCENT;
- } else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=6 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==0) {
- fmt = PixelFormat.RGB_565;
- }
- /* else if(rCaps.getRedBits()<=5 &&
- rCaps.getGreenBits()<=5 &&
- rCaps.getBlueBits()<=5 &&
- rCaps.getAlphaBits()==1) {
- fmt = PixelFormat.RGBA_5551; // FIXME: Supported ?
- } */
- else {
- fmt = PixelFormat.RGBA_8888;
- }
- Log.d(MD.TAG, "getFormat: requested: "+rCaps);
- Log.d(MD.TAG, "getFormat: returned: "+fmt);
-
- return fmt;
- }
-
- public static boolean isAndroidFormatTransparent(int aFormat) {
- switch (aFormat) {
- case PixelFormat.TRANSLUCENT:
- case PixelFormat.TRANSPARENT:
- return true;
- }
- return false;
- }
-
- class AndroidEvents implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener {
-
- @Override
- public boolean onTouch(View v, android.view.MotionEvent event) {
- final com.jogamp.newt.event.MouseEvent[] newtEvents = AndroidNewtEventFactory.createMouseEvents(event, AndroidWindow.this);
- if(null != newtEvents) {
- focusChanged(false, true);
- for(int i=0; i<newtEvents.length; i++) {
- AndroidWindow.this.enqueueEvent(false, newtEvents[i]);
- }
- try { Thread.sleep((long) (1000.0F/30.0F)); }
- catch(InterruptedException e) { }
- return true; // consumed/handled, further interest in events
- }
- return false; // no mapping, no further interest in the event!
- }
-
- @Override
- public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
- final com.jogamp.newt.event.KeyEvent[] newtEvents = AndroidNewtEventFactory.createKeyEvents(keyCode, event, AndroidWindow.this);
- if(null != newtEvents) {
- for(int i=0; i<newtEvents.length; i++) {
- AndroidWindow.this.enqueueEvent(false, newtEvents[i]);
- }
- return true;
- }
- return false;
- }
-
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- AndroidWindow.this.focusChanged(false, hasFocus);
- }
-
- }
-
- public static Class<?>[] getCustomConstructorArgumentTypes() {
- return new Class<?>[] { Context.class } ;
- }
-
- public AndroidWindow() {
- reset();
- }
-
- private void reset() {
- ownAndroidWindow = false;
- androidView = null;
- nativeFormat = VisualIDHolder.VID_UNDEFINED;
- androidFormat = VisualIDHolder.VID_UNDEFINED;
- capsByFormat = null;
- surface = null;
- surfaceHandle = 0;
- eglSurface = 0;
- definePosition(0, 0); // default to 0/0
- setBrokenFocusChange(true);
- }
-
- @Override
- protected void instantiationFinished() {
- final Context ctx = StaticContext.getContext();
- if(null == ctx) {
- throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
- }
- androidView = new MSurfaceView(ctx);
-
- final AndroidEvents ae = new AndroidEvents();
- androidView.setOnTouchListener(ae);
- androidView.setClickable(false);
- androidView.setOnKeyListener(ae);
- androidView.setOnFocusChangeListener(ae);
- androidView.setFocusable(true);
- androidView.setFocusableInTouchMode(true);
-
- final SurfaceHolder sh = androidView.getHolder();
- sh.addCallback(AndroidWindow.this);
- sh.setFormat(getFormat(getRequestedCapabilities()));
-
- // default size -> TBD !
- defineSize(0, 0);
- }
-
- public SurfaceView getAndroidView() { return androidView; }
-
- @Override
- protected boolean canCreateNativeImpl() {
- final boolean b = 0 != surfaceHandle;
- Log.d(MD.TAG, "canCreateNativeImpl: "+b);
- return b;
- }
-
- @Override
- protected void createNativeImpl() {
- Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
- ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName());
-
- if(0!=getParentWindowHandle()) {
- throw new NativeWindowException("Window parenting not supported (yet)");
- }
- if(0==surfaceHandle) {
- throw new InternalError("XXX");
- }
-
- final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice();
- final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(),
- (GLCapabilitiesChooser)capabilitiesChooser, getScreen().getGraphicsScreen(), nativeFormat,
- isAndroidFormatTransparent(androidFormat));
- if (eglConfig == null) {
- throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
- }
- final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE);
- Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID));
- if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) {
- setSurfaceVisualID0(surfaceHandle, nativeVisualID);
- }
-
- eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null);
- if (EGL.EGL_NO_SURFACE==eglSurface) {
- throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError()));
- }
-
- // propagate data ..
- setGraphicsConfiguration(eglConfig);
- setWindowHandle(surfaceHandle);
- focusChanged(false, true);
- Log.d(MD.TAG, "createNativeImpl X");
- }
-
- @Override
- protected void closeNativeImpl() {
- release0(surfaceHandle);
- surface = null;
- surfaceHandle = 0;
- eglSurface = 0;
- }
-
- @Override
- public final long getSurfaceHandle() {
- return eglSurface;
- }
-
- protected void requestFocusImpl(boolean reparented) {
- if(null != androidView) {
- Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented);
- androidView.post(new Runnable() {
- public void run() {
- androidView.requestFocus();
- androidView.bringToFront();
- }
- });
- }
- }
-
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
- Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a");
- return false;
- }
- if(width>0 || height>0) {
- if(0!=getWindowHandle()) {
- Log.d(MD.TAG, "reconfigureWindowImpl.setSize n/a");
- return false;
- }
- }
- if(x>=0 || y>=0) {
- Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a");
- return false;
- }
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
- }
- return true;
- }
-
- protected Point getLocationOnScreenImpl(int x, int y) {
- return new Point(x,y);
- }
-
- protected void updateInsetsImpl(Insets insets) {
- // nop ..
- }
-
- //----------------------------------------------------------------------
- // Surface Callbacks
- //
-
- public void surfaceCreated(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
- }
-
- public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) {
- Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle));
- if(0!=surfaceHandle && androidFormat != aFormat ) {
- // re-create
- Log.d(MD.TAG, "surfaceChanged (destroy old)");
- if(!windowDestroyNotify(true)) {
- destroy();
- }
- surfaceHandle = 0;
- surface=null;
- }
- if(getScreen().isNativeValid()) {
- getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event
- }
-
- if(0>getX() || 0>getY()) {
- positionChanged(false, 0, 0);
- }
-
- if(0 == surfaceHandle) {
- androidFormat = aFormat;
- surface = aHolder.getSurface();
- surfaceHandle = getSurfaceHandle0(surface);
- acquire0(surfaceHandle);
- nativeFormat = getSurfaceVisualID0(surfaceHandle);
- final int nWidth = getWidth0(surfaceHandle);
- final int nHeight = getHeight0(surfaceHandle);
- capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities());
- sizeChanged(false, nWidth, nHeight, false);
-
- Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+
- ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
- ", format [a "+androidFormat+"/n "+nativeFormat+"], "+
- getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible());
-
- if(isVisible()) {
- setVisible(true);
- }
- }
- sizeChanged(false, aWidth, aHeight, false);
- windowRepaint(0, 0, aWidth, aHeight);
- Log.d(MD.TAG, "surfaceChanged: X");
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceDestroyed");
- windowDestroyNotify(true); // actually too late .. however ..
- }
-
- public void surfaceRedrawNeeded(SurfaceHolder holder) {
- Log.d(MD.TAG, "surfaceRedrawNeeded");
- windowRepaint(0, 0, getWidth(), getHeight());
- }
-
- private boolean ownAndroidWindow;
- private MSurfaceView androidView;
- private int nativeFormat; // chosen current native PixelFormat (suitable for EGL)
- private int androidFormat; // chosen current android PixelFormat (-1, -2 ..)
- private GLCapabilitiesImmutable capsByFormat; // fixed requestedCaps by PixelFormat
- private Surface surface;
- private volatile long surfaceHandle;
- private long eglSurface;
-
- class MSurfaceView extends SurfaceView {
- public MSurfaceView (Context ctx) {
- super(ctx);
- setBackgroundDrawable(null);
- // setBackgroundColor(Color.TRANSPARENT);
- }
- }
- //----------------------------------------------------------------------
- // Internals only
- //
- protected static native boolean initIDs0();
- protected static native long getSurfaceHandle0(Surface surface);
- protected static native int getSurfaceVisualID0(long surfaceHandle);
- protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID);
- protected static native int getWidth0(long surfaceHandle);
- protected static native int getHeight0(long surfaceHandle);
- protected static native void acquire0(long surfaceHandle);
- protected static native void release0(long surfaceHandle);
-}
diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
index 3f360f20f..32bd970a1 100644
--- a/src/newt/classes/jogamp/newt/driver/android/AndroidDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,7 +20,7 @@
* 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.
@@ -32,15 +32,12 @@ import jogamp.newt.*;
import jogamp.opengl.egl.*;
import javax.media.nativewindow.*;
-import javax.media.opengl.GLException;
-
-import com.jogamp.nativewindow.egl.*;
-public class AndroidDisplay extends jogamp.newt.DisplayImpl {
+public class DisplayDriver extends jogamp.newt.DisplayImpl {
static {
NEWTJNILibLoader.loadNEWT();
- if (!AndroidWindow.initIDs0()) {
+ if (!WindowDriver.initIDs0()) {
throw new NativeWindowException("Failed to initialize Android NEWT Windowing library");
}
}
@@ -50,29 +47,21 @@ public class AndroidDisplay extends jogamp.newt.DisplayImpl {
}
- public AndroidDisplay() {
+ public DisplayDriver() {
}
protected void createNativeImpl() {
// EGL Device
- final long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- aDevice = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
}
- protected void closeNativeImpl() {
- if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
- EGLDisplayUtil.eglTerminate(aDevice.getHandle());
- }
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ aDevice.close();
}
protected void dispatchMessagesNative() {
// n/a .. DispatchMessages();
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java
index 150dea9c7..f2f30937b 100644
--- a/src/newt/classes/jogamp/newt/driver/android/MD.java
+++ b/src/newt/classes/jogamp/newt/driver/android/MD.java
@@ -43,7 +43,7 @@ public class MD {
.append(JoglVersion.getInstance()).append(Platform.NEWLINE)
.append(Platform.NEWLINE);
- JoglVersion.getDefaultOpenGLInfo(sb);
+ JoglVersion.getDefaultOpenGLInfo(null, sb, true);
return sb.toString();
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
index 4537fa963..76eb890e2 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java
@@ -32,11 +32,14 @@ import java.util.List;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
import com.jogamp.newt.Window;
-import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
-import jogamp.newt.driver.android.AndroidWindow;
+import jogamp.newt.driver.android.WindowDriver;
import android.app.Activity;
import android.content.Context;
@@ -46,12 +49,46 @@ import android.view.WindowManager;
public class NewtBaseActivity extends Activity {
List<Window> newtWindows = new ArrayList<Window>();
- Animator animator = null;
+ List<GLAutoDrawable> glAutoDrawables = new ArrayList<GLAutoDrawable>();
+
+ GLAnimatorControl animator = null;
boolean isDelegatedActivity;
Activity rootActivity;
boolean setThemeCalled = false;
+ protected void startAnimation(boolean start) {
+ if(null != animator) {
+ final boolean res;
+ if( start ) {
+ if( animator.isPaused() ) {
+ res = animator.resume();
+ } else {
+ res = animator.start();
+ }
+ } else {
+ res = animator.stop();
+ }
+ Log.d(MD.TAG, "Animator global: start "+start+", result "+res);
+ }
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAnimatorControl anim = glAutoDrawables.get(i).getAnimator();
+ if(null != anim) {
+ final boolean res;
+ if( start ) {
+ if( anim.isPaused() ) {
+ res = anim.resume();
+ } else {
+ res = anim.start();
+ }
+ } else {
+ res = anim.stop();
+ }
+ Log.d(MD.TAG, "Animator glad["+i+"]: start "+start+", result "+res);
+ }
+ }
+ }
+
public NewtBaseActivity() {
super();
isDelegatedActivity = false;
@@ -59,8 +96,8 @@ public class NewtBaseActivity extends Activity {
}
public void setRootActivity(Activity rootActivity) {
- this.isDelegatedActivity = true;
this.rootActivity = rootActivity;
+ this.isDelegatedActivity = this != rootActivity;
}
public final boolean isDelegatedActivity() {
@@ -79,19 +116,21 @@ public class NewtBaseActivity extends Activity {
* </p>
* @param androidWindow
* @param newtWindow
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
+ * @see #registerNEWTWindow(Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(android.view.Window androidWindow, Window newtWindow) {
- newtWindow = newtWindow.getDelegatedWindow();
- if(newtWindow instanceof AndroidWindow) {
- adaptTheme4Transparency(newtWindow.getRequestedCapabilities());
- layoutForNEWTWindow(androidWindow, newtWindow);
- AndroidWindow newtAWindow = (AndroidWindow)newtWindow;
+ public void setContentView(final android.view.Window androidWindow, final Window newtWindow) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ if(delegateWindow instanceof WindowDriver) {
+ adaptTheme4Transparency(delegateWindow.getRequestedCapabilities());
+ layoutForNEWTWindow(androidWindow, delegateWindow);
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.setContentView(newtAWindow.getAndroidView());
- registerNEWTWindow(newtAWindow);
} else {
- throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass());
+ throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass().getName());
}
+ registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
@@ -102,32 +141,68 @@ public class NewtBaseActivity extends Activity {
* @param androidWindow
* @param newtWindow
* @param params
- * @see #setContentView(android.view.Window, Window)
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #registerNEWTWindow(Window)
+ * @see #setContentView(android.view.Window, Window)
*/
- public void addContentView(android.view.Window androidWindow, Window newtWindow, android.view.ViewGroup.LayoutParams params) {
- newtWindow = newtWindow.getDelegatedWindow();
- if(newtWindow instanceof AndroidWindow) {
- AndroidWindow newtAWindow = (AndroidWindow)newtWindow;
+ public void addContentView(final android.view.Window androidWindow, final Window newtWindow, final android.view.ViewGroup.LayoutParams params) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ if(delegateWindow instanceof WindowDriver) {
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.addContentView(newtAWindow.getAndroidView(), params);
- registerNEWTWindow(newtAWindow);
} else {
- throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass());
+ throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
}
+ registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
* <p>
- * This methods simply registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
- * </p>
+ * This methods registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
+ * </p>
+ * <p>
+ * If adding a {@link GLAutoDrawable} implementation, the {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()}
+ * will be used for {@link #onPause()} and {@link #onResume()}.
+ * </p>
+ * <p>
+ * If adding a {@link GLAutoDrawable} implementation, the {@link GLEventListenerState} will preserve it's state
+ * when {@link #onPause()} is being called while not {@link #isFinishing()}. A later {@link #onResume()} will
+ * reinstate the {@link GLEventListenerState}.
+ * </p>
*
* @param newtWindow
+ * @throws IllegalArgumentException if the <code>newtWindow</code>'s {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #setContentView(android.view.Window, Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
- public void registerNEWTWindow(Window newtWindow) {
+ public void registerNEWTWindow(final Window newtWindow) throws IllegalArgumentException {
+ final Window delegateWindow = newtWindow.getDelegatedWindow();
+ Log.d(MD.TAG, "registerNEWTWindow: Type "+newtWindow.getClass().getName()+", delegate "+delegateWindow.getClass().getName());
+ if(delegateWindow instanceof WindowDriver) {
+ final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
+ newtAWindow.registerActivity(getActivity());
+ } else {
+ throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
+ }
newtWindows.add(newtWindow);
+ if(newtWindow instanceof GLAutoDrawable) {
+ glAutoDrawables.add((GLAutoDrawable)newtWindow);
+ }
+ if(newtWindow instanceof GLStateKeeper) {
+ ((GLStateKeeper)newtWindow).setGLStateKeeperListener(glStateKeeperListener);
+ }
}
+ private final GLStateKeeper.Listener glStateKeeperListener = new GLStateKeeper.Listener() {
+ @Override
+ public void glStatePreserveNotify(GLStateKeeper glsk) {
+ Log.d(MD.TAG, "GLStateKeeper Preserving: 0x"+Integer.toHexString(glsk.hashCode()));
+ }
+ @Override
+ public void glStateRestored(GLStateKeeper glsk) {
+ Log.d(MD.TAG, "GLStateKeeper Restored: 0x"+Integer.toHexString(glsk.hashCode()));
+ startAnimation(true);
+ }
+ };
/**
* Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
@@ -221,7 +296,19 @@ public class NewtBaseActivity extends Activity {
}
}
- public void setAnimator(Animator animator) {
+ /**
+ * Setting up a global {@Link GLAnimatorControl} for {@link #onPause()} and {@link #onResume()}.
+ * <p>
+ * Note that if adding a {@link GLAutoDrawable} implementation via {@link #registerNEWTWindow(Window)},
+ * {@link #setContentView(android.view.Window, Window)} or {@link #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)}
+ * their {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} will be used as well.
+ * In this case, using this global {@Link GLAnimatorControl} is redundant.
+ * </p>
+ * @see #registerNEWTWindow(Window)
+ * @see #setContentView(android.view.Window, Window)
+ * @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
+ */
+ public void setAnimator(GLAnimatorControl animator) {
this.animator = animator;
if(!animator.isStarted()) {
animator.start();
@@ -231,85 +318,146 @@ public class NewtBaseActivity extends Activity {
@Override
public android.view.Window getWindow() {
- return getActivity().getWindow();
+ if( isDelegatedActivity() ) {
+ return getActivity().getWindow();
+ } else {
+ return super.getWindow();
+ }
}
@Override
public void onCreate(Bundle savedInstanceState) {
- Log.d(MD.TAG, "onCreate");
+ Log.d(MD.TAG, "onCreate.0");
if(!isDelegatedActivity()) {
super.onCreate(savedInstanceState);
}
+ // Extraordinary cleanup, for cases of 'onCreate()' calls w/ valid states,
+ // i.e. w/o having onDestroy() being called.
+ // Could happened due to spec when App process is killed for memory exhaustion or other reasons.
+ cleanup();
+
jogamp.common.os.android.StaticContext.init(rootActivity.getApplicationContext());
+ Log.d(MD.TAG, "onCreate.X");
}
@Override
public void onStart() {
- Log.d(MD.TAG, "onStart");
+ Log.d(MD.TAG, "onStart.0");
if(!isDelegatedActivity()) {
super.onStart();
}
+ Log.d(MD.TAG, "onStart.X");
}
@Override
public void onRestart() {
- Log.d(MD.TAG, "onRestart");
+ Log.d(MD.TAG, "onRestart.0");
if(!isDelegatedActivity()) {
super.onRestart();
}
+ Log.d(MD.TAG, "onRestart.X");
}
@Override
public void onResume() {
- Log.d(MD.TAG, "onResume");
+ Log.d(MD.TAG, "onResume.0");
if(!isDelegatedActivity()) {
super.onResume();
}
- if(null != animator) {
- animator.resume();
- animator.resetFPSCounter();
- }
- for(int i=newtWindows.size()-1; i>=0; i--) {
+ for(int i=0; i<newtWindows.size(); i++) {
final Window win = newtWindows.get(i);
+ win.setVisible(true);
if(win instanceof FPSCounter) {
((FPSCounter)win).resetFPSCounter();
}
}
+ startAnimation(true);
+ Log.d(MD.TAG, "onResume.X");
}
@Override
public void onPause() {
- Log.d(MD.TAG, "onPause");
- if(null != animator) {
- animator.pause();
+ Log.d(MD.TAG, "onPause.0");
+ if( !getActivity().isFinishing() ) {
+ int ok=0, fail=0;
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAutoDrawable glad = glAutoDrawables.get(i);
+ if(glad instanceof GLStateKeeper) {
+ if( ((GLStateKeeper)glad).preserveGLStateAtDestroy(true) ) {
+ ok++;
+ } else {
+ fail++;
+ }
+ }
+ }
+ Log.d(MD.TAG, "GLStateKeeper.Mark2Preserve: Total "+glAutoDrawables.size()+", OK "+ok+", Fail "+fail);
}
- if(!isDelegatedActivity()) {
+ startAnimation(false);
+ if( !isDelegatedActivity() ) {
super.onPause();
}
+ Log.d(MD.TAG, "onPause.X");
}
@Override
public void onStop() {
- Log.d(MD.TAG, "onStop");
- if(!isDelegatedActivity()) {
+ Log.d(MD.TAG, "onStop.0");
+ for(int i=0; i<newtWindows.size(); i++) {
+ final Window win = newtWindows.get(i);
+ win.setVisible(false);
+ }
+ if( !isDelegatedActivity() ) {
super.onStop();
}
+ Log.d(MD.TAG, "onStop.X");
}
-
- @Override
- public void onDestroy() {
- Log.d(MD.TAG, "onDestroy");
- if(null != animator) {
- animator.stop();
- animator = null;
+
+ /**
+ * Performs cleaning up all references,
+ * <p>
+ * Cleaning and destroying up all preserved GLEventListenerState
+ * and clearing the preserve-flag of all GLStateKeeper.
+ * </p>
+ * <p>
+ * Destroying all GLWindow.
+ * </p>
+ */
+ private void cleanup() {
+ Log.d(MD.TAG, "cleanup.0");
+ int glelsKilled = 0, glelsClean = 0;
+ for(int i=0; i<glAutoDrawables.size(); i++) {
+ final GLAutoDrawable glad = glAutoDrawables.get(i);
+ if(glad instanceof GLStateKeeper) {
+ final GLStateKeeper glsk = (GLStateKeeper)glad;
+ glsk.preserveGLStateAtDestroy(false);
+ final GLEventListenerState glels = glsk.clearPreservedGLState();
+ if( null != glels) {
+ glels.destroy();
+ glelsKilled++;
+ } else {
+ glelsClean++;
+ }
+ }
}
- while(newtWindows.size()>0) {
- final Window win = newtWindows.remove(newtWindows.size()-1);
+ Log.d(MD.TAG, "cleanup.1: GLStateKeeper.ForceDestroy: Total "+glAutoDrawables.size()+", destroyed "+glelsKilled+", clean "+glelsClean);
+ for(int i=0; i<newtWindows.size(); i++) {
+ final Window win = newtWindows.get(i);
win.destroy();
}
+ newtWindows.clear();
+ glAutoDrawables.clear();
+ Log.d(MD.TAG, "cleanup.1: StaticContext.getContext: "+jogamp.common.os.android.StaticContext.getContext());
jogamp.common.os.android.StaticContext.clear();
+ Log.d(MD.TAG, "cleanup.X");
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(MD.TAG, "onDestroy.0");
+ cleanup(); // normal cleanup
if(!isDelegatedActivity()) {
super.onDestroy();
}
+ Log.d(MD.TAG, "onDestroy.X");
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
index 36b83337a..259acb8f3 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,7 +20,7 @@
* 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.
@@ -47,58 +47,75 @@ import android.widget.ScrollView;
import android.widget.TextView;
public class NewtVersionActivity extends NewtBaseActivity {
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
setFullscreenFeature(getWindow(), true);
final android.view.ViewGroup viewGroup = new android.widget.FrameLayout(getActivity().getApplicationContext());
getWindow().setContentView(viewGroup);
-
+
final TextView tv = new TextView(getActivity());
final ScrollView scroller = new ScrollView(getActivity());
scroller.addView(tv);
viewGroup.addView(scroller, new android.widget.FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, Gravity.TOP|Gravity.LEFT));
-
- tv.setText(VersionUtil.getPlatformInfo()+Platform.NEWLINE+GlueGenVersion.getInstance()+Platform.NEWLINE+JoglVersion.getInstance()+Platform.NEWLINE);
-
- // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
- GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GLES2));
- GLWindow glWindow = GLWindow.create(caps);
- glWindow.setUndecorated(true);
- glWindow.setSize(32, 32);
- glWindow.setPosition(0, 0);
- final android.view.View androidGLView = ((AndroidWindow)glWindow.getDelegatedWindow()).getAndroidView();
- viewGroup.addView(androidGLView, new android.widget.FrameLayout.LayoutParams(glWindow.getWidth(), glWindow.getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
- registerNEWTWindow(glWindow);
-
- glWindow.addGLEventListener(new GLEventListener() {
- public void init(GLAutoDrawable drawable) {
- GL gl = drawable.getGL();
- final StringBuffer sb = new StringBuffer();
- sb.append(JoglVersion.getGLInfo(gl, null)).append(Platform.NEWLINE);
- sb.append("Requested: ").append(Platform.NEWLINE);
- sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
- sb.append("Chosen: ").append(Platform.NEWLINE);
- sb.append(drawable.getChosenGLCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
- viewGroup.post(new Runnable() {
- public void run() {
- tv.append(sb.toString());
- viewGroup.removeView(androidGLView);
- } } );
- }
- public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
- }
+ final String info1 = "JOGL Version Info"+Platform.NEWLINE+VersionUtil.getPlatformInfo()+Platform.NEWLINE+GlueGenVersion.getInstance()+Platform.NEWLINE+JoglVersion.getInstance()+Platform.NEWLINE;
+ Log.d(MD.TAG, info1);
+ tv.setText(info1);
+
+ final GLProfile glp;
+ if( GLProfile.isAvailable(GLProfile.GL2ES2) ) {
+ glp = GLProfile.get(GLProfile.GL2ES2);
+ } else if( GLProfile.isAvailable(GLProfile.GL2ES1) ) {
+ glp = GLProfile.get(GLProfile.GL2ES1);
+ } else {
+ glp = null;
+ tv.append("No GLProfile GL2ES2 nor GL2ES1 available!");
+ }
+ if( null != glp ) {
+ // create GLWindow (-> incl. underlying NEWT Display, Screen & Window)
+ GLCapabilities caps = new GLCapabilities(glp);
+ GLWindow glWindow = GLWindow.create(caps);
+ glWindow.setUndecorated(true);
+ glWindow.setSize(32, 32);
+ glWindow.setPosition(0, 0);
+ final android.view.View androidGLView = ((WindowDriver)glWindow.getDelegatedWindow()).getAndroidView();
+ viewGroup.addView(androidGLView, new android.widget.FrameLayout.LayoutParams(glWindow.getWidth(), glWindow.getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+ registerNEWTWindow(glWindow);
+
+ glWindow.addGLEventListener(new GLEventListener() {
+ public void init(GLAutoDrawable drawable) {
+ GL gl = drawable.getGL();
+ final StringBuilder sb = new StringBuilder();
+ sb.append(JoglVersion.getGLInfo(gl, null, true)).append(Platform.NEWLINE);
+ sb.append("Requested: ").append(Platform.NEWLINE);
+ sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
+ sb.append("Chosen: ").append(Platform.NEWLINE);
+ sb.append(drawable.getChosenGLCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
+ final String info2 = sb.toString();
+ // Log.d(MD.TAG, info2); // too big!
+ System.err.println(info2);
+ viewGroup.post(new Runnable() {
+ public void run() {
+ tv.append(info2);
+ viewGroup.removeView(androidGLView);
+ } } );
+ }
+
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ }
- public void display(GLAutoDrawable drawable) {
- }
+ public void display(GLAutoDrawable drawable) {
+ }
- public void dispose(GLAutoDrawable drawable) {
- }
- });
- glWindow.setVisible(true);
+ public void dispose(GLAutoDrawable drawable) {
+ }
+ });
+ glWindow.setVisible(true);
+ }
Log.d(MD.TAG, "onCreate - X");
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
index cb8799b19..553900f6a 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivityLauncher.java
@@ -10,12 +10,12 @@ public class NewtVersionActivityLauncher extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity");
- final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
+
+ final Uri uri = Uri.parse("launch://jogamp.org/jogamp.newt.driver.android.NewtVersionActivity?sys=com.jogamp.common&sys=javax.media.opengl&pkg=com.jogamp.opengl.test&jogamp.debug=all&nativewindow.debug=all&jogl.debug=all&newt.debug=all");
+ final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri);
Log.d(getClass().getSimpleName(), "Launching Activity: "+intent);
startActivity (intent);
-
+
finish(); // done
- }
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
new file mode 100644
index 000000000..66237204c
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2011 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.android;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.MonitorModeProps.Cache;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.util.DisplayMetrics;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends jogamp.newt.ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // FIXME: only one screen available ?
+ }
+
+ private final MonitorMode getModeImpl(final Cache cache, final android.view.Display aDisplay, DisplayMetrics outMetrics, int modeIdx, int screenSizeNRot, int nrot) {
+ final int[] props = new int[MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ i = getScreenSize(outMetrics, screenSizeNRot, props, i); // width, height
+ i = getBpp(aDisplay, props, i); // bpp
+ props[i++] = (int) ( aDisplay.getRefreshRate() * 100.0f ); // Hz * 100
+ props[i++] = 0; // flags
+ props[i++] = modeIdx; // modeId;
+ props[i++] = nrot;
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ }
+
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(Cache cache) {
+ // FIXME: Multi Monitor Implementation missing [for newer Android version ?]
+
+ final Context ctx = jogamp.common.os.android.StaticContext.getContext();
+ final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ final DisplayMetrics outMetrics = new DisplayMetrics();
+ final android.view.Display aDisplay = wmgr.getDefaultDisplay();
+ aDisplay.getMetrics(outMetrics);
+
+ final int arot = aDisplay.getRotation();
+ final int nrot = androidRotation2NewtRotation(arot);
+
+ final int modeIdx=0; // no native modeId in use - use 0
+ MonitorMode currentMode = null;
+ for(int r=0; r<4; r++) { // for all rotations
+ final int nrot_i = r*MonitorMode.ROTATE_90;
+ MonitorMode mode = getModeImpl(cache, aDisplay, outMetrics, modeIdx, 0, nrot_i);
+ if( nrot == nrot_i ) {
+ currentMode = mode;
+ }
+ }
+
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ i = getScreenSizeMM(outMetrics, props, i); // sizeMM
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = outMetrics.widthPixels; // rotated viewport width
+ props[i++] = outMetrics.heightPixels; // rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+ final Context ctx = jogamp.common.os.android.StaticContext.getContext();
+ final WindowManager wmgr = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
+ final DisplayMetrics outMetrics = new DisplayMetrics();
+ final android.view.Display aDisplay = wmgr.getDefaultDisplay();
+ aDisplay.getMetrics(outMetrics);
+
+ final int currNRot = androidRotation2NewtRotation(aDisplay.getRotation());
+ return getModeImpl(null, aDisplay, outMetrics, 0, currNRot, currNRot);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+ return false;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ static int androidRotation2NewtRotation(int arot) {
+ switch(arot) {
+ case Surface.ROTATION_270: return MonitorMode.ROTATE_270;
+ case Surface.ROTATION_180: return MonitorMode.ROTATE_180;
+ case Surface.ROTATION_90: return MonitorMode.ROTATE_90;
+ case Surface.ROTATION_0:
+ }
+ return MonitorMode.ROTATE_0;
+ }
+ static int getScreenSize(DisplayMetrics outMetrics, int nrot, int[] props, int offset) {
+ // swap width and height, since Android reflects rotated dimension, we don't
+ if (MonitorMode.ROTATE_90 == nrot || MonitorMode.ROTATE_270 == nrot) {
+ props[offset++] = outMetrics.heightPixels;
+ props[offset++] = outMetrics.widthPixels;
+ } else {
+ props[offset++] = outMetrics.widthPixels;
+ props[offset++] = outMetrics.heightPixels;
+ }
+ return offset;
+ }
+ static int getBpp(android.view.Display aDisplay, int[] props, int offset) {
+ int bpp;
+ switch(aDisplay.getPixelFormat()) {
+ case PixelFormat.RGBA_8888: bpp=32; break;
+ case PixelFormat.RGBX_8888: bpp=32; break;
+ case PixelFormat.RGB_888: bpp=24; break;
+ case PixelFormat.RGB_565: bpp=16; break;
+ case PixelFormat.RGBA_5551: bpp=16; break;
+ case PixelFormat.RGBA_4444: bpp=16; break;
+ case PixelFormat.RGB_332: bpp= 8; break;
+ default: bpp=32;
+ }
+ props[offset++] = bpp;
+ return offset;
+ }
+ static int getScreenSizeMM(DisplayMetrics outMetrics, int[] props, int offset) {
+ final float inW = outMetrics.widthPixels / outMetrics.xdpi;
+ final float inH = outMetrics.heightPixels / outMetrics.ydpi;
+ final float mmpi = 25.4f;
+ final float mmW = inW * mmpi;
+ final float mmH = inH * mmpi;
+ if( DEBUG ) {
+ System.err.println("Screen A screen "+outMetrics.widthPixels+" x "+outMetrics.heightPixels);
+ System.err.println("Screen A xy dpi "+outMetrics.xdpi+" x "+outMetrics.ydpi);
+ System.err.println("Screen A densityDPI "+outMetrics.densityDpi);
+ System.err.println("Screen A density "+outMetrics.density);
+ System.err.println("Screen N xy inch "+inW+" x "+inH);
+ System.err.println("Screen N xy mm "+mmW+" x "+mmH);
+ }
+ props[offset++] = Math.round(mmW);
+ props[offset++] = Math.round(mmH);
+ return offset;
+ }
+}
+
diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
new file mode 100644
index 000000000..9af455445
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
@@ -0,0 +1,715 @@
+/**
+ * Copyright 2011 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.android;
+
+import jogamp.common.os.android.StaticContext;
+import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
+import jogamp.newt.driver.android.event.AndroidNewtEventTranslator;
+
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.CapabilitiesImmutable;
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.RectangleImmutable;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.newt.MonitorDevice;
+
+import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLDisplayUtil;
+import jogamp.opengl.egl.EGLGraphicsConfiguration;
+import jogamp.opengl.egl.EGLGraphicsConfigurationFactory;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback2;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+
+
+public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ /**
+ * First stage of selecting an Android PixelFormat,
+ * at construction via {@link SurfaceHolder#setFormat(int)}
+ * before native realization!
+ *
+ * @param rCaps requested Capabilities
+ * @return An Android PixelFormat number suitable for {@link SurfaceHolder#setFormat(int)}.
+ */
+ public static final int getSurfaceHolderFormat(CapabilitiesImmutable rCaps) {
+ int fmt = PixelFormat.UNKNOWN;
+
+ if( !rCaps.isBackgroundOpaque() ) {
+ fmt = PixelFormat.TRANSLUCENT;
+ } else if( rCaps.getRedBits()<=5 &&
+ rCaps.getGreenBits()<=6 &&
+ rCaps.getBlueBits()<=5 &&
+ rCaps.getAlphaBits()==0 ) {
+ fmt = PixelFormat.RGB_565;
+ } else if( rCaps.getAlphaBits()==0 ) {
+ fmt = PixelFormat.RGB_888;
+ } else {
+ fmt = PixelFormat.RGBA_8888;
+ }
+ Log.d(MD.TAG, "getSurfaceHolderFormat: requested: "+rCaps);
+ Log.d(MD.TAG, "getSurfaceHolderFormat: returned: "+fmt);
+
+ return fmt;
+ }
+
+
+ public static final int NATIVE_WINDOW_FORMAT_RGBA_8888 = 1;
+ public static final int NATIVE_WINDOW_FORMAT_RGBX_8888 = 2;
+ public static final int NATIVE_WINDOW_FORMAT_RGB_565 = 4;
+
+ /**
+ * Second stage of selecting an Android PixelFormat,
+ * at right after native (surface) realization at {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+ * Selection happens via {@link #setSurfaceVisualID0(long, int)} before native EGL creation.
+ *
+ * @param androidPixelFormat An Android PixelFormat delivered via {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)} params.
+ * @return A native Android PixelFormat number suitable for {@link #setSurfaceVisualID0(long, int)}.
+ */
+ public static final int getANativeWindowFormat(int androidPixelFormat) {
+ final int nativePixelFormat;
+ switch(androidPixelFormat) {
+ case PixelFormat.RGBA_8888:
+ case PixelFormat.RGBA_5551:
+ case PixelFormat.RGBA_4444:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888;
+ break;
+
+ case PixelFormat.RGBX_8888:
+ case PixelFormat.RGB_888:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBX_8888;
+ break;
+
+ case PixelFormat.RGB_565:
+ case PixelFormat.RGB_332:
+ nativePixelFormat = NATIVE_WINDOW_FORMAT_RGB_565;
+ break;
+ default: nativePixelFormat = NATIVE_WINDOW_FORMAT_RGBA_8888;
+ }
+ Log.d(MD.TAG, "getANativeWindowFormat: android: "+androidPixelFormat+" -> native "+nativePixelFormat);
+ return nativePixelFormat;
+ }
+
+ /**
+ * Final stage of Android PixelFormat operation,
+ * match the requested Capabilities w/ Android PixelFormat number.
+ * This is done at native realization @ {@link Callback2#surfaceChanged(SurfaceHolder, int, int, int)}.
+ *
+ * @param matchFormatPrecise
+ * @param format
+ * @param rCaps requested Capabilities
+ * @return The fixed Capabilities
+ */
+ public static final CapabilitiesImmutable fixCaps(boolean matchFormatPrecise, int format, CapabilitiesImmutable rCaps) {
+ PixelFormat pf = new PixelFormat();
+ PixelFormat.getPixelFormatInfo(format, pf);
+ final CapabilitiesImmutable res;
+ int r, g, b, a;
+
+ switch(format) {
+ case PixelFormat.RGBA_8888: r=8; g=8; b=8; a=8; break; // NATIVE_WINDOW_FORMAT_RGBA_8888
+ case PixelFormat.RGBX_8888: r=8; g=8; b=8; a=0; break; // NATIVE_WINDOW_FORMAT_RGBX_8888
+ case PixelFormat.RGB_888: r=8; g=8; b=8; a=0; break;
+ case PixelFormat.RGB_565: r=5; g=6; b=5; a=0; break; // NATIVE_WINDOW_FORMAT_RGB_565
+ case PixelFormat.RGBA_5551: r=5; g=5; b=5; a=1; break;
+ case PixelFormat.RGBA_4444: r=4; g=4; b=4; a=4; break;
+ case PixelFormat.RGB_332: r=3; g=3; b=2; a=0; break;
+ default: throw new InternalError("Unhandled pixelformat: "+format);
+ }
+ final boolean change = matchFormatPrecise ||
+ rCaps.getRedBits() > r &&
+ rCaps.getGreenBits() > g &&
+ rCaps.getBlueBits() > b &&
+ rCaps.getAlphaBits() > a ;
+
+ if(change) {
+ Capabilities nCaps = (Capabilities) rCaps.cloneMutable();
+ nCaps.setRedBits(r);
+ nCaps.setGreenBits(g);
+ nCaps.setBlueBits(b);
+ nCaps.setAlphaBits(a);
+ res = nCaps;
+ } else {
+ res = rCaps;
+ }
+ Log.d(MD.TAG, "fixCaps: format: "+format);
+ Log.d(MD.TAG, "fixCaps: requested: "+rCaps);
+ Log.d(MD.TAG, "fixCaps: chosen: "+res);
+
+ return res;
+ }
+
+ public static final boolean isAndroidFormatTransparent(int aFormat) {
+ switch (aFormat) {
+ case PixelFormat.TRANSLUCENT:
+ case PixelFormat.TRANSPARENT:
+ return true;
+ }
+ return false;
+ }
+
+ public static Class<?>[] getCustomConstructorArgumentTypes() {
+ return new Class<?>[] { Context.class } ;
+ }
+
+ public WindowDriver() {
+ reset();
+ }
+
+ public void registerActivity(Activity activity) {
+ this.activity = activity;
+ }
+ protected Activity activity = null;
+
+ private final void reset() {
+ added2StaticViewGroup = false;
+ androidView = null;
+ nativeFormat = VisualIDHolder.VID_UNDEFINED;
+ androidFormat = VisualIDHolder.VID_UNDEFINED;
+ capsByFormat = null;
+ surface = null;
+ surfaceHandle = 0;
+ eglSurface = 0;
+ definePosition(0, 0); // default to 0/0
+ defineSize(0, 0); // default size -> TBD !
+
+ setBrokenFocusChange(true);
+ }
+
+ private final void setupInputListener(final boolean enable) {
+ Log.d(MD.TAG, "setupInputListener(enable "+enable+") - "+Thread.currentThread().getName());
+
+ final AndroidNewtEventTranslator eventTranslator =
+ enable ? new AndroidNewtEventTranslator(this, androidView.getContext(), androidView.getHandler()) : null;
+ androidView.setOnTouchListener(eventTranslator);
+ androidView.setOnKeyListener(eventTranslator);
+ androidView.setOnFocusChangeListener(eventTranslator);
+ if(AndroidVersion.SDK_INT >= 12) { // API Level 12
+ Log.d(MD.TAG, "setupInputListener - enable GenericMotionListener - "+Thread.currentThread().getName());
+ androidView.setOnGenericMotionListener(eventTranslator);
+ }
+ if( enable ) {
+ androidView.post(new Runnable() {
+ public void run() {
+ androidView.setClickable(false);
+ androidView.setFocusable(true);
+ androidView.setFocusableInTouchMode(true);
+ } } );
+ }
+ }
+
+ private final void setupAndroidView(Context ctx) {
+ androidView = new MSurfaceView(ctx);
+
+ final SurfaceHolder sh = androidView.getHolder();
+ sh.addCallback(WindowDriver.this);
+ sh.setFormat(getSurfaceHolderFormat(getRequestedCapabilities()));
+ }
+
+ public final SurfaceView getAndroidView() { return androidView; }
+
+ @Override
+ protected final void instantiationFinished() {
+ Log.d(MD.TAG, "instantiationFinished() - "+Thread.currentThread().getName());
+
+ final Context ctx = StaticContext.getContext();
+ if(null == ctx) {
+ throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
+ }
+
+ if( null != Looper.myLooper() ) {
+ setupAndroidView(ctx);
+ }
+ }
+
+ @Override
+ protected final boolean canCreateNativeImpl() {
+ Log.d(MD.TAG, "canCreateNativeImpl.0: surfaceHandle ready "+(0!=surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+ if(WindowImpl.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
+
+ if( isFullscreen() ) {
+ final MonitorDevice mainMonitor = getMainMonitor();
+ final RectangleImmutable viewport = mainMonitor.getViewport();
+ definePosition(viewport.getX(), viewport.getY());
+ defineSize(viewport.getWidth(), viewport.getHeight());
+ }
+
+ final boolean b;
+
+ if( 0 == surfaceHandle ) {
+ // Static ViewGroup, i.e. self contained main code
+ final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+ Log.d(MD.TAG, "canCreateNativeImpl: viewGroup "+viewGroup);
+ if( null != viewGroup && !added2StaticViewGroup ) {
+ added2StaticViewGroup = true;
+ viewGroup.post(new Runnable() {
+ public void run() {
+ if(null == androidView) {
+ setupAndroidView( StaticContext.getContext() );
+ }
+ viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(getWidth(), getHeight(), Gravity.BOTTOM|Gravity.RIGHT));
+ Log.d(MD.TAG, "canCreateNativeImpl: added to static ViewGroup - on thread "+Thread.currentThread().getName());
+ } });
+ for(long sleep = TIMEOUT_NATIVEWINDOW; 0<sleep && 0 == surfaceHandle; sleep-=10 ) {
+ try { Thread.sleep(10); } catch (InterruptedException ie) {}
+ }
+ b = 0 != surfaceHandle;
+ Log.d(MD.TAG, "canCreateNativeImpl: surfaceHandle ready(2) "+b+" - on thread "+Thread.currentThread().getName());
+ } else {
+ // No surfaceHandle defined, No static ViewGroup to add ourselves
+ b = false;
+ }
+ } else {
+ // surfaceHandle already defined
+ b = true;
+ }
+ return b;
+ }
+
+ @Override
+ protected final void createNativeImpl() {
+ // Create own screen/device resource instance allowing independent ownership,
+ // while still utilizing shared EGL resources.
+ final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
+ final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+ eglDevice.open();
+ final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
+
+ Log.d(MD.TAG, "createNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+ ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
+
+ if(0!=getParentWindowHandle()) {
+ throw new NativeWindowException("Window parenting not supported (yet)");
+ }
+ if(0==surfaceHandle) {
+ throw new InternalError("surfaceHandle null");
+ }
+
+ final EGLGraphicsConfiguration eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
+ capsByFormat, (GLCapabilitiesImmutable) getRequestedCapabilities(),
+ (GLCapabilitiesChooser)capabilitiesChooser, eglScreen, nativeFormat, isAndroidFormatTransparent(androidFormat));
+ if (eglConfig == null) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ final int nativeVisualID = eglConfig.getVisualID(VisualIDHolder.VIDType.NATIVE);
+ Log.d(MD.TAG, "nativeVisualID 0x"+Integer.toHexString(nativeVisualID));
+ Log.d(MD.TAG, "requestedCaps: "+eglConfig.getRequestedCapabilities());
+ Log.d(MD.TAG, "chosenCaps : "+eglConfig.getChosenCapabilities());
+ if(VisualIDHolder.VID_UNDEFINED != nativeVisualID) {
+ setSurfaceVisualID0(surfaceHandle, nativeVisualID);
+ }
+
+ eglSurface = EGL.eglCreateWindowSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surfaceHandle, null);
+ if (EGL.EGL_NO_SURFACE==eglSurface) {
+ throw new NativeWindowException("Creation of window surface failed: "+eglConfig+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", error "+toHexString(EGL.eglGetError()));
+ }
+
+ // propagate data ..
+ setGraphicsConfiguration(eglConfig);
+ setWindowHandle(surfaceHandle);
+ visibleChanged(false, true);
+ focusChanged(false, true);
+
+ setupInputListener(true);
+
+ Log.d(MD.TAG, "createNativeImpl X: eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", eglSurfaceHandle 0x"+Long.toHexString(eglSurface));
+ }
+
+ @Override
+ protected final void closeNativeImpl() {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+
+ Log.d(MD.TAG, "closeNativeImpl 0 - eglDevice 0x"+Integer.toHexString(eglDevice.hashCode())+", "+eglDevice+", surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+ ", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)+
+ ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
+ if(WindowImpl.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
+
+ setupInputListener(false);
+
+ if(0 != eglSurface) {
+ try {
+ if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) {
+ throw new GLException("Error destroying window surface (eglDestroySurface)");
+ }
+ } catch (Throwable t) {
+ Log.d(MD.TAG, "closeNativeImpl: Catch exception "+t.getMessage());
+ t.printStackTrace();
+ } finally {
+ eglSurface = 0;
+ }
+ }
+ release0(surfaceHandle);
+
+ eglDevice.close();
+
+ if( null != androidView ) {
+ if( added2StaticViewGroup ) {
+ added2StaticViewGroup = false;
+ final ViewGroup viewGroup = StaticContext.getContentViewGroup();
+ if( null != viewGroup) {
+ viewGroup.post(new Runnable() {
+ public void run() {
+ viewGroup.removeView(androidView);
+ Log.d(MD.TAG, "closeNativeImpl: removed from static ViewGroup - on thread "+Thread.currentThread().getName());
+ } });
+ }
+ }
+ }
+
+ surface = null;
+ surfaceHandle = 0;
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return eglSurface;
+ }
+
+ /**
+ * <p>
+ * Accessible protected method!
+ * </p>
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public final void focusChanged(boolean defer, boolean focusGained) {
+ super.focusChanged(defer, focusGained);
+ }
+
+ @Override
+ protected final void requestFocusImpl(boolean reparented) {
+ if(null != androidView) {
+ Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented);
+ androidView.post(new Runnable() {
+ public void run() {
+ androidView.requestFocus();
+ androidView.bringToFront();
+ }
+ });
+ }
+ }
+
+ @Override
+ protected final boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ boolean res = true;
+
+ if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
+ Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a");
+ return false;
+ }
+ if(getWidth() != width || getHeight() != height) {
+ if(0!=getWindowHandle()) {
+ Log.d(MD.TAG, "reconfigureWindowImpl.setSize n/a");
+ res = false;
+ } else {
+ defineSize(width, height);
+ }
+ }
+ if(getX() != x || getY() != y) {
+ if(0!=getWindowHandle()) {
+ Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a");
+ res = false;
+ } else {
+ definePosition(x, y);
+ }
+ }
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
+ visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+ }
+ return res;
+ }
+
+ @Override
+ protected final Point getLocationOnScreenImpl(int x, int y) {
+ return new Point(x,y);
+ }
+
+ @Override
+ protected final void updateInsetsImpl(Insets insets) {
+ // nop ..
+ }
+
+ //----------------------------------------------------------------------
+ // Virtual On-Screen Keyboard / SoftInput
+ //
+
+ private class KeyboardVisibleReceiver extends ResultReceiver {
+ public KeyboardVisibleReceiver() {
+ super(null);
+ }
+
+ @Override
+ public void onReceiveResult(int r, Bundle data) {
+ boolean v = false;
+
+ switch(r) {
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ case InputMethodManager.RESULT_SHOWN:
+ v = true;
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ v = false;
+ break;
+ }
+ Log.d(MD.TAG, "keyboardVisible: "+v);
+ keyboardVisibilityChanged(v);
+ }
+ }
+ private final KeyboardVisibleReceiver keyboardVisibleReceiver = new KeyboardVisibleReceiver();
+
+ @Override
+ protected final boolean setKeyboardVisibleImpl(boolean visible) {
+ if(null != androidView) {
+ final InputMethodManager imm = (InputMethodManager) getAndroidView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ final IBinder winid = getAndroidView().getWindowToken();
+ final boolean result;
+ if(visible) {
+ // Show soft-keyboard:
+ result = imm.showSoftInput(androidView, 0, keyboardVisibleReceiver);
+ } else {
+ // hide keyboard :
+ result = imm.hideSoftInputFromWindow(winid, 0, keyboardVisibleReceiver);
+ }
+ return result;
+ } else {
+ return false; // nop
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Surface Callbacks
+ //
+
+ @Override
+ public final void surfaceCreated(SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - on thread "+Thread.currentThread().getName());
+ }
+
+ @Override
+ public final void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) {
+ Log.d(MD.TAG, "surfaceChanged: f "+nativeFormat+" -> "+aFormat+", "+aWidth+"x"+aHeight+", current surfaceHandle: 0x"+Long.toHexString(surfaceHandle)+" - on thread "+Thread.currentThread().getName());
+ if(WindowImpl.DEBUG_IMPLEMENTATION) {
+ Thread.dumpStack();
+ }
+ if(0!=surfaceHandle && androidFormat != aFormat ) {
+ // re-create
+ Log.d(MD.TAG, "surfaceChanged (destroy old)");
+ if(!windowDestroyNotify(true)) {
+ destroy();
+ }
+ surfaceHandle = 0;
+ surface=null;
+ }
+ if(getScreen().isNativeValid()) {
+ // if MonitorMode changed .. trigger MonitorMode event
+ final MonitorDevice mainMonitor = getMainMonitor();
+ mainMonitor.queryCurrentMode();
+ }
+
+ if(0>getX() || 0>getY()) {
+ positionChanged(false, 0, 0);
+ }
+
+ if(0 == surfaceHandle) {
+ androidFormat = aFormat;
+ surface = aHolder.getSurface();
+ surfaceHandle = getSurfaceHandle0(surface);
+ acquire0(surfaceHandle);
+ final int aNativeWindowFormat = getANativeWindowFormat(androidFormat);
+ setSurfaceVisualID0(surfaceHandle, aNativeWindowFormat);
+ nativeFormat = getSurfaceVisualID0(surfaceHandle);
+ Log.d(MD.TAG, "surfaceChanged: androidFormat "+androidFormat+" -- (set-native "+aNativeWindowFormat+") --> nativeFormat "+nativeFormat);
+
+ final int nWidth = getWidth0(surfaceHandle);
+ final int nHeight = getHeight0(surfaceHandle);
+ capsByFormat = (GLCapabilitiesImmutable) fixCaps(true /* matchFormatPrecise */, nativeFormat, getRequestedCapabilities());
+ sizeChanged(false, nWidth, nHeight, false);
+
+ Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+
+ ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+
+ ", format [a "+androidFormat+"/n "+nativeFormat+"], "+
+ getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible());
+
+ if(isVisible()) {
+ setVisible(false, true);
+ }
+ }
+ sizeChanged(false, aWidth, aHeight, false);
+ windowRepaint(0, 0, aWidth, aHeight);
+ Log.d(MD.TAG, "surfaceChanged: X");
+ }
+
+ @Override
+ public final void surfaceDestroyed(SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceDestroyed - on thread "+Thread.currentThread().getName());
+ windowDestroyNotify(true); // actually too late .. however ..
+ Thread.dumpStack();
+ }
+
+ @Override
+ public final void surfaceRedrawNeeded(SurfaceHolder holder) {
+ Log.d(MD.TAG, "surfaceRedrawNeeded - on thread "+Thread.currentThread().getName());
+ windowRepaint(0, 0, getWidth(), getHeight());
+ }
+
+ protected boolean handleKeyCodeBack(KeyEvent.DispatcherState state, android.view.KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+ Log.d(MD.TAG, "handleKeyCodeBack.0 : "+event);
+ state.startTracking(event, this);
+ } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) {
+ // Since we cannot trust the visibility state 'completly',
+ // assume an already invisible state if the invisible operation fails.
+ final boolean wasVisible = setKeyboardVisibleImpl(false);
+ Log.d(MD.TAG, "handleKeyCodeBack.1 : wasVisible "+wasVisible+": "+event);
+ keyboardVisibilityChanged(false);
+ if( wasVisible ) {
+ // event processed, just send invisible event, no activity.finished()
+ enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_KEYBOARD_INVISIBLE);
+ return true;
+ } else if( null != activity ) {
+ // process event on our own, since we have an activity to call finish()
+ // and decide in overriden consumeKeyEvent(..) whether we suppress or proceed w/ activity.finish().
+ enqueueAKey2NKeyUpDown(event, com.jogamp.newt.event.KeyEvent.VK_ESCAPE);
+ return true;
+ } else {
+ Log.d(MD.TAG, "handleKeyCodeBack.X1 : "+event);
+ windowDestroyNotify(true);
+ // -> default BACK action, usually activity.finish()
+ }
+ }
+ return false; // continue w/ further processing
+ }
+ private void enqueueAKey2NKeyUpDown(android.view.KeyEvent aEvent, short newtKeyCode) {
+ final com.jogamp.newt.event.KeyEvent eDown = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED, this);
+ final com.jogamp.newt.event.KeyEvent eUp = AndroidNewtEventFactory.createKeyEvent(aEvent, newtKeyCode, com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, this);
+ enqueueEvent(false, eDown);
+ enqueueEvent(false, eUp);
+ }
+
+ @Override
+ protected void consumeKeyEvent(com.jogamp.newt.event.KeyEvent e) {
+ super.consumeKeyEvent(e); // consume event, i.e. call all KeyListener
+ if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == e.getEventType() && !e.isConsumed() ) {
+ if( com.jogamp.newt.event.KeyEvent.VK_ESCAPE == e.getKeyCode() ) {
+ Log.d(MD.TAG, "handleKeyCodeBack.X2 : "+e);
+ activity.finish();
+ } else if( com.jogamp.newt.event.KeyEvent.VK_HOME == e.getKeyCode() ) {
+ Log.d(MD.TAG, "handleKeyCodeHome.X2 : "+e);
+ triggerHome();
+ }
+ }
+ }
+ private void triggerHome() {
+ Context ctx = StaticContext.getContext();
+ if(null == ctx) {
+ throw new NativeWindowException("No static [Application] Context has been set. Call StaticContext.setContext(Context) first.");
+ }
+ Intent showOptions = new Intent(Intent.ACTION_MAIN);
+ showOptions.addCategory(Intent.CATEGORY_HOME);
+ ctx.startActivity(showOptions);
+ }
+
+ private boolean added2StaticViewGroup;
+ private MSurfaceView androidView;
+ private int nativeFormat; // chosen current native PixelFormat (suitable for EGL)
+ private int androidFormat; // chosen current android PixelFormat (-1, -2 ..)
+ private GLCapabilitiesImmutable capsByFormat; // fixed requestedCaps by PixelFormat
+ private Surface surface;
+ private volatile long surfaceHandle;
+ private long eglSurface;
+
+ class MSurfaceView extends SurfaceView {
+ public MSurfaceView (Context ctx) {
+ super(ctx);
+ setBackgroundDrawable(null);
+ // setBackgroundColor(Color.TRANSPARENT);
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ Log.d(MD.TAG, "onKeyPreIme : "+event);
+ if ( event.getKeyCode() == KeyEvent.KEYCODE_BACK ) {
+ final KeyEvent.DispatcherState state = getKeyDispatcherState();
+ if (state != null) {
+ return handleKeyCodeBack(state, event);
+ }
+ }
+ return false; // cont. processing
+ }
+ }
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ protected static native boolean initIDs0();
+ protected static native long getSurfaceHandle0(Surface surface);
+ /** Return the native window format via <code>ANativeWindow_getFormat(..)</code>. */
+ protected static native int getSurfaceVisualID0(long surfaceHandle);
+ /** Set the native window format via <code>ANativeWindow_setBuffersGeometry(..)</code>. */
+ protected static native void setSurfaceVisualID0(long surfaceHandle, int nativeVisualID);
+ protected static native int getWidth0(long surfaceHandle);
+ protected static native int getHeight0(long surfaceHandle);
+ protected static native void acquire0(long surfaceHandle);
+ protected static native void release0(long surfaceHandle);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
index d23b5f576..e5d667f3e 100644
--- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java
@@ -28,49 +28,88 @@
package jogamp.newt.driver.android.event;
-import java.awt.event.MouseEvent;
+import jogamp.newt.Debug;
+import android.view.MotionEvent;
-import com.jogamp.common.util.IntIntHashMap;
-import com.jogamp.newt.Window;
+import com.jogamp.common.os.AndroidVersion;
import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.NEWTEvent;
public class AndroidNewtEventFactory {
-
- protected static final IntIntHashMap eventTypeANDROID2NEWT;
-
- private static final String names[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
- "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
+ private static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Android.MouseEvent");
+ private static final boolean DEBUG_KEY_EVENT = Debug.debug("Android.KeyEvent");
- static {
- IntIntHashMap map = new IntIntHashMap();
- map.setKeyNotFoundValue(0xFFFFFFFF);
-
- map.put(android.view.MotionEvent.ACTION_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(android.view.MotionEvent.ACTION_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(android.view.MotionEvent.ACTION_CANCEL, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
- map.put(android.view.MotionEvent.ACTION_MOVE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED);
- map.put(android.view.MotionEvent.ACTION_OUTSIDE, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED);
-
- map.put(android.view.MotionEvent.ACTION_POINTER_DOWN, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED);
- map.put(android.view.MotionEvent.ACTION_POINTER_UP, com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED);
-
- map.put(android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS);
+ /** API Level 12: {@link android.view.MotionEvent#ACTION_SCROLL} = {@value} */
+ private static final int ACTION_SCROLL = 8;
- eventTypeANDROID2NEWT = map;
+ private static final com.jogamp.newt.event.MouseEvent.PointerType aToolType2PointerType(int aToolType) {
+ switch( aToolType ) {
+ case MotionEvent.TOOL_TYPE_FINGER:
+ return com.jogamp.newt.event.MouseEvent.PointerType.TouchScreen;
+ case MotionEvent.TOOL_TYPE_MOUSE:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Mouse;
+ case MotionEvent.TOOL_TYPE_STYLUS:
+ case MotionEvent.TOOL_TYPE_ERASER:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Pen;
+ default:
+ return com.jogamp.newt.event.MouseEvent.PointerType.Undefined;
+ }
+ }
+
+ private static final short aMotionEventType2Newt(int aType) {
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case android.view.MotionEvent.ACTION_UP:
+ case android.view.MotionEvent.ACTION_POINTER_UP:
+ case android.view.MotionEvent.ACTION_CANCEL:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case android.view.MotionEvent.ACTION_MOVE:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case android.view.MotionEvent.ACTION_OUTSIDE:
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ // case ACTION_HOVER_MOVE
+ case ACTION_SCROLL: // API Level 12 !
+ return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ // case ACTION_HOVER_ENTER
+ // case ACTION_HOVER_EXIT
+ }
+ return (short)0;
+ }
+
+ private static final short aAccessibilityEventType2Newt(int aType) {
+ switch( aType ) {
+ case android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED:
+ return com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS;
+ }
+ return (short)0;
}
- static final int androidKeyCode2Newt(int androidKeyCode) {
+ private static final short aKeyEventType2NewtEventType(int androidKeyAction) {
+ switch(androidKeyAction) {
+ case android.view.KeyEvent.ACTION_DOWN:
+ case android.view.KeyEvent.ACTION_MULTIPLE:
+ return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case android.view.KeyEvent.ACTION_UP:
+ return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
+ }
+
+ private static final short aKeyCode2NewtKeyCode(int androidKeyCode, boolean inclSysKeys) {
if(android.view.KeyEvent.KEYCODE_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_9) {
- return com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_0 ) );
}
if(android.view.KeyEvent.KEYCODE_A <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_Z) {
- return com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_A + ( androidKeyCode - android.view.KeyEvent.KEYCODE_A ) );
}
if(android.view.KeyEvent.KEYCODE_F1 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_F12) {
- return com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_F1 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_F1 ) );
}
if(android.view.KeyEvent.KEYCODE_NUMPAD_0 <= androidKeyCode && androidKeyCode <= android.view.KeyEvent.KEYCODE_NUMPAD_9) {
- return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) ;
+ return (short) ( com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 + ( androidKeyCode - android.view.KeyEvent.KEYCODE_NUMPAD_0 ) );
}
switch(androidKeyCode) {
case android.view.KeyEvent.KEYCODE_COMMA: return com.jogamp.newt.event.KeyEvent.VK_COMMA;
@@ -82,7 +121,7 @@ public class AndroidNewtEventFactory {
case android.view.KeyEvent.KEYCODE_TAB: return com.jogamp.newt.event.KeyEvent.VK_TAB;
case android.view.KeyEvent.KEYCODE_SPACE: return com.jogamp.newt.event.KeyEvent.VK_SPACE;
case android.view.KeyEvent.KEYCODE_ENTER: return com.jogamp.newt.event.KeyEvent.VK_ENTER;
- case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case android.view.KeyEvent.KEYCODE_DEL: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
case android.view.KeyEvent.KEYCODE_MINUS: return com.jogamp.newt.event.KeyEvent.VK_MINUS;
case android.view.KeyEvent.KEYCODE_EQUALS: return com.jogamp.newt.event.KeyEvent.VK_EQUALS;
case android.view.KeyEvent.KEYCODE_LEFT_BRACKET: return com.jogamp.newt.event.KeyEvent.VK_LEFT_PARENTHESIS;
@@ -95,24 +134,29 @@ public class AndroidNewtEventFactory {
// case android.view.KeyEvent.KEYCODE_MUTE: ??
case android.view.KeyEvent.KEYCODE_PAGE_UP: return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
case android.view.KeyEvent.KEYCODE_PAGE_DOWN: return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
- // case android.view.KeyEvent.KEYCODE_HOME: return com.jogamp.newt.event.KeyEvent.VK_HOME;
- // case android.view.KeyEvent.KEYCODE_BACK: return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
case android.view.KeyEvent.KEYCODE_ESCAPE: return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
case android.view.KeyEvent.KEYCODE_CTRL_LEFT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
case android.view.KeyEvent.KEYCODE_CTRL_RIGHT: return com.jogamp.newt.event.KeyEvent.VK_CONTROL; // ??
+ case android.view.KeyEvent.KEYCODE_BACK:
+ if( inclSysKeys ) {
+ // Note that manual mapping is performed, based on the keyboard state.
+ // I.e. we map to VK_KEYBOARD_INVISIBLE if keyboard was visible and now becomes invisible!
+ // Otherwise we map to VK_ESCAPE, and if not consumed by user, the application will be terminated.
+ return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ }
+ break;
+ case android.view.KeyEvent.KEYCODE_HOME:
+ if( inclSysKeys ) {
+ // If not consumed by user, the application will be 'paused',
+ // i.e. resources (GLEventListener) pulled before surface gets destroyed!
+ return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ }
+ break;
}
- return 0;
+ return com.jogamp.newt.event.KeyEvent.VK_UNDEFINED;
}
- public static final com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
- int type = eventTypeANDROID2NEWT.get(event.getEventType());
- if(0xFFFFFFFF != type) {
- return new com.jogamp.newt.event.WindowEvent(type, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
- }
- return null; // no mapping ..
- }
-
- static final int androidKeyModifiers2Newt(int androidMods) {
+ private static final int aKeyModifiers2Newt(int androidMods) {
int newtMods = 0;
if ((androidMods & android.view.KeyEvent.META_SYM_ON) != 0) newtMods |= com.jogamp.newt.event.InputEvent.META_MASK;
if ((androidMods & android.view.KeyEvent.META_SHIFT_ON) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
@@ -121,123 +165,200 @@ public class AndroidNewtEventFactory {
return newtMods;
}
- private static final int androidKeyAction2NewtEventType(int androidKeyAction) {
- switch(androidKeyAction) {
- case android.view.KeyEvent.ACTION_DOWN:
- case android.view.KeyEvent.ACTION_MULTIPLE:
- return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
- case android.view.KeyEvent.ACTION_UP:
- return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
- default:
- return 0;
+ public static com.jogamp.newt.event.WindowEvent createWindowEvent(android.view.accessibility.AccessibilityEvent event, com.jogamp.newt.Window newtSource) {
+ final int aType = event.getEventType();
+ final short nType = aAccessibilityEventType2Newt(aType);
+
+ if( (short)0 != nType) {
+ return new com.jogamp.newt.event.WindowEvent(nType, ((null==newtSource)?null:(Object)newtSource), event.getEventTime());
}
+ return null; // no mapping ..
}
+
- public static final com.jogamp.newt.event.KeyEvent[] createKeyEvents(int keyCode, android.view.KeyEvent event, com.jogamp.newt.Window newtSource) {
- final int type = androidKeyAction2NewtEventType(event.getAction());
- if(Window.DEBUG_MOUSE_EVENT) {
- System.err.println("createKeyEvent: type 0x"+Integer.toHexString(type)+", keyCode 0x"+Integer.toHexString(keyCode)+", "+event);
- }
- if(0xFFFFFFFF != type) {
- final int newtKeyCode = androidKeyCode2Newt(keyCode);
- if(0 != newtKeyCode) {
- final Object src = (null==newtSource)?null:(Object)newtSource;
- final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
- final int newtMods = androidKeyModifiers2Newt(event.getMetaState());
-
- final com.jogamp.newt.event.KeyEvent ke1 = new com.jogamp.newt.event.KeyEvent(
- type, src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel());
-
- if( com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED == type ) {
- return new com.jogamp.newt.event.KeyEvent[] { ke1,
- new com.jogamp.newt.event.KeyEvent(
- com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED,
- src, unixTime, newtMods, newtKeyCode, event.getDisplayLabel()) };
- } else {
- return new com.jogamp.newt.event.KeyEvent[] { ke1 };
- }
- }
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+ final com.jogamp.newt.event.KeyEvent res;
+ final short newtType = aKeyEventType2NewtEventType(aEvent.getAction());
+ if( (short)0 != newtType) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ } else {
+ res = null;
+ }
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent0: "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtType, com.jogamp.newt.Window newtSource, boolean inclSysKeys) {
+ final short newtKeyCode = aKeyCode2NewtKeyCode(aEvent.getKeyCode(), inclSysKeys);
+ final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent1: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ public static com.jogamp.newt.event.KeyEvent createKeyEvent(android.view.KeyEvent aEvent, short newtKeyCode, short newtType, com.jogamp.newt.Window newtSource) {
+ final com.jogamp.newt.event.KeyEvent res = createKeyEventImpl(aEvent, newtType, newtKeyCode, newtSource);
+ if(DEBUG_KEY_EVENT) {
+ System.err.println("createKeyEvent2: newtType "+NEWTEvent.toHexString(newtType)+", "+aEvent+" -> "+res);
+ }
+ return res;
+ }
+
+ private static com.jogamp.newt.event.KeyEvent createKeyEventImpl(android.view.KeyEvent aEvent, short newtType, short newtKeyCode, com.jogamp.newt.Window newtSource) {
+ if( (short)0 != newtType && com.jogamp.newt.event.KeyEvent.VK_UNDEFINED != newtKeyCode ) {
+ final Object src = null==newtSource ? null : newtSource;
+ final long unixTime = System.currentTimeMillis() + ( aEvent.getEventTime() - android.os.SystemClock.uptimeMillis() );
+ final int newtMods = aKeyModifiers2Newt(aEvent.getMetaState());
+
+ return com.jogamp.newt.event.KeyEvent.create(
+ newtType, src, unixTime, newtMods, newtKeyCode, newtKeyCode, (char) aEvent.getUnicodeChar());
}
return null;
}
+
+ private static float maxPressure = 0.7f; // experienced maximum value (Amazon HD = 0.8f)
+
+ /**
+ * Dynamic calibration of maximum MotionEvent pressure, starting from 0.7f
+ * <p>
+ * Specification says no pressure is 0.0f and
+ * normal pressure is 1.0f, where &gt; 1.0f denominates very high pressure.
+ * </p>
+ * <p>
+ * Some devices exceed this spec, or better, most devices do.
+ * <ul>
+ * <li>Asus TF2*: Pressure always &gt; 1.0f</li>
+ * <li>Amazon HD: Pressure always &le; 0.8f</li>
+ * </ul>
+ * </p>
+ *
+ * @return
+ */
+ public static float getMaxPressure() {
+ return maxPressure;
+ }
+
+ private final int touchSlop;
+ public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) {
+ final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context);
+ touchSlop = configuration.getScaledTouchSlop();
+ final int doubleTapSlop = configuration.getScaledDoubleTapSlop();
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("AndroidNewtEventFactory scrollSlop (scaled) "+touchSlop);
+ System.err.println("AndroidNewtEventFactory doubleTapSlop (scaled) "+doubleTapSlop);
+ }
+ }
+
+ private static void collectPointerData(MotionEvent e, int idx, final int[] x, final int[] y, final float[] pressure,
+ final short[] pointerIds, final MouseEvent.PointerType[] pointerTypes) {
+ x[idx] = (int)e.getX(idx);
+ y[idx] = (int)e.getY(idx);
+ pressure[idx] = e.getPressure(idx);
+ pointerIds[idx] = (short)e.getPointerId(idx);
+ if( pressure[idx] > maxPressure ) {
+ maxPressure = pressure[idx];
+ }
+ pointerTypes[idx] = aToolType2PointerType( e.getToolType(idx) );
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: ptr-data["+idx+"] "+x[idx]+"/"+y[idx]+", pressure "+pressure[idx]+", id "+pointerIds[idx]+", type "+pointerTypes[idx]);
+ }
+ }
+
+ public boolean sendPointerEvent(boolean enqueue, boolean wait, boolean setFocusOnDown, boolean isOnTouchEvent,
+ android.view.MotionEvent event, jogamp.newt.driver.android.WindowDriver newtSource) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: isOnTouchEvent "+isOnTouchEvent+", "+event);
+ }
- public static final com.jogamp.newt.event.MouseEvent[] createMouseEvents(android.view.MotionEvent event, com.jogamp.newt.Window newtSource) {
- if(Window.DEBUG_MOUSE_EVENT) {
- System.err.println("createMouseEvent: "+toString(event));
- }
- int type = eventTypeANDROID2NEWT.get(event.getAction());
- if(0xFFFFFFFF != type) {
- int rotation = 0;
- int clickCount = 1;
+ if( event.getPressure() > maxPressure ) {
+ maxPressure = event.getPressure();
+ }
+
+ //
+ // Prefilter Android Event (Gesture, ..) and determine final type
+ //
+ final int aType = event.getActionMasked();
+ final short nType = aMotionEventType2Newt(aType);
+ final float rotationScale = touchSlop;
+ final float[] rotationXYZ = new float[] { 0f, 0f, 0f };
+
+ if( (short)0 != nType ) {
int modifiers = 0;
- int[] x = new int[event.getPointerCount()];
- int[] y = new int[event.getPointerCount()];
- float[] pressure = new float[event.getPointerCount()];
- int[] pointers = new int[event.getPointerCount()];
- int index = 0;
- while(index < event.getPointerCount()) {
- x[index] = (int)event.getX(index);
- y[index] = (int)event.getY(index);
- pressure[index] = event.getPressure(index);
- pointers[index] = event.getPointerId(index);
- index++;
+ //
+ // Determine SDK 12 SCROLL, newt-button and whether dedicated pointer is pressed
+ //
+ final int pIndex;
+ final short button;
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_UP: {
+ pIndex = event.getActionIndex();
+ final int b = event.getPointerId(pIndex) + 1; // FIXME: Assumption that Pointer-ID starts w/ 0 !
+ if( com.jogamp.newt.event.MouseEvent.BUTTON1 <= b && b <= com.jogamp.newt.event.MouseEvent.BUTTON_COUNT ) {
+ button = (short)b;
+ } else {
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
+ }
+ break;
+
+ case ACTION_SCROLL:
+ if( AndroidVersion.SDK_INT >= 12 ) { // API Level 12
+ rotationXYZ[0] = event.getAxisValue(android.view.MotionEvent.AXIS_X) / rotationScale;
+ rotationXYZ[1] = event.getAxisValue(android.view.MotionEvent.AXIS_Y) / rotationScale;
+
+ if( rotationXYZ[0]*rotationXYZ[0] > rotationXYZ[1]*rotationXYZ[1] ) {
+ // Horizontal
+ modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ }
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: SDK-12 Scroll "+rotationXYZ[0]+"/"+rotationXYZ[1]+", "+rotationScale+", mods "+modifiers);
+ }
+ }
+ // Fall through intended!
+
+ default: {
+ pIndex = 0;
+ button = com.jogamp.newt.event.MouseEvent.BUTTON1;
+ }
+ }
+ final int pCount = event.getPointerCount(); // all
+
+ switch( aType ) {
+ case android.view.MotionEvent.ACTION_DOWN:
+ case android.view.MotionEvent.ACTION_POINTER_DOWN:
+ modifiers |= InputEvent.getButtonMask(button);
+ if( setFocusOnDown ) {
+ newtSource.focusChanged(false, true);
+ }
}
- if(null!=newtSource) {
- if(newtSource.isPointerConfined()) {
- modifiers |= InputEvent.CONFINED_MASK;
+ //
+ // Collect common data
+ //
+ final int[] x = new int[pCount];
+ final int[] y = new int[pCount];
+ final float[] pressure = new float[pCount];
+ final short[] pointerIds = new short[pCount];
+ final MouseEvent.PointerType[] pointerTypes = new MouseEvent.PointerType[pCount];
+ if( 0 < pCount ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("createMouseEvent: collect ptr-data [0.."+(pCount-1)+", count "+pCount+", action "+pIndex+"], aType "+aType+", button "+button);
}
- if(!newtSource.isPointerVisible()) {
- modifiers |= InputEvent.INVISIBLE_MASK;
+ for(int i=0; i < pCount; i++) {
+ collectPointerData(event, i, x, y, pressure, pointerIds, pointerTypes);
}
}
-
- final Object src = (null==newtSource)?null:(Object)newtSource;
- final long unixTime = System.currentTimeMillis() + ( event.getEventTime() - android.os.SystemClock.uptimeMillis() );
- final int button = pointers.length==1 ? MouseEvent.BUTTON1 : 0;
-
- final com.jogamp.newt.event.MouseEvent me1 = new com.jogamp.newt.event.MouseEvent(
- type, src, unixTime,
- modifiers, x, y, pressure, pointers, clickCount,
- button, rotation);
-
- if(type == com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED) {
- return new com.jogamp.newt.event.MouseEvent[] { me1,
- new com.jogamp.newt.event.MouseEvent(
- com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED,
- src, unixTime, modifiers, x, y, pressure, pointers, clickCount,
- button, rotation) };
- } else {
- return new com.jogamp.newt.event.MouseEvent[] { me1 };
- }
- }
- return null; // no mapping ..
+ newtSource.doPointerEvent(enqueue, wait, pointerTypes, nType, modifiers,
+ pIndex, pointerIds, x, y, pressure, maxPressure, rotationXYZ, rotationScale);
+ return true;
+ }
+ return false; // no mapping ..
}
-
-
- public static String toString(android.view.MotionEvent event) {
- StringBuilder sb = new StringBuilder();
- int action = event.getAction();
- int actionCode = action & android.view.MotionEvent.ACTION_MASK;
- sb.append("ACTION_" ).append(names[actionCode]);
- if (actionCode == android.view.MotionEvent.ACTION_POINTER_DOWN
- || actionCode == android.view.MotionEvent.ACTION_POINTER_UP) {
- sb.append("(pid " ).append(
- action >> android.view.MotionEvent.ACTION_POINTER_ID_SHIFT);
- sb.append(")" );
- }
- sb.append("[" );
- for (int i = 0; i < event.getPointerCount(); i++) {
- sb.append("#" ).append(i);
- sb.append("(pid " ).append(event.getPointerId(i));
- sb.append(")=" ).append((int) event.getX(i));
- sb.append("," ).append((int) event.getY(i));
- if (i + 1 < event.getPointerCount())
- sb.append(";" );
- }
- sb.append("]" );
- return sb.toString();
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
new file mode 100644
index 000000000..5a4743f73
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventTranslator.java
@@ -0,0 +1,50 @@
+package jogamp.newt.driver.android.event;
+
+import jogamp.newt.driver.android.WindowDriver;
+import android.view.View;
+
+public class AndroidNewtEventTranslator implements View.OnKeyListener, View.OnTouchListener, View.OnFocusChangeListener, View.OnGenericMotionListener {
+ private final WindowDriver newtWindow;
+ private final AndroidNewtEventFactory factory;
+
+ public AndroidNewtEventTranslator(WindowDriver newtWindow, android.content.Context context, android.os.Handler handler) {
+ this.newtWindow = newtWindow;
+ this.factory = new AndroidNewtEventFactory(context, handler);
+ }
+
+ private final boolean processTouchMotionEvents(View v, android.view.MotionEvent event, boolean isOnTouchEvent) {
+ final boolean eventSent = factory.sendPointerEvent(true /*enqueue*/, false /*wait*/, true /*setFocusOnDown*/,
+ isOnTouchEvent, event, newtWindow);
+ if( eventSent ) {
+ try { Thread.sleep((long) (100.0F/3.0F)); } // 33 ms - FIXME ??
+ catch(InterruptedException e) { }
+ return true; // consumed/handled, further interest in events
+ }
+ return false; // no mapping, no further interest in the event!
+ }
+
+ @Override
+ public boolean onTouch(View v, android.view.MotionEvent event) {
+ return processTouchMotionEvents(v, event, true);
+ }
+
+ @Override
+ public boolean onGenericMotion(View v, android.view.MotionEvent event) {
+ return processTouchMotionEvents(v, event, false);
+ }
+
+ @Override
+ public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
+ final com.jogamp.newt.event.KeyEvent newtEvent = AndroidNewtEventFactory.createKeyEvent(event, newtWindow, false /* no system keys */);
+ if(null != newtEvent) {
+ newtWindow.enqueueEvent(false, newtEvent);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ newtWindow.focusChanged(false, hasFocus);
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
index 5a49dd57c..f7722c91c 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,12 +29,13 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
import java.awt.Canvas;
+import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsConfiguration;
import java.lang.reflect.Method;
@@ -45,19 +47,23 @@ import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeWindow;
import javax.media.nativewindow.NativeWindowException;
-
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.VisualIDHolder;
import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.awt.JAWTWindow;
import com.jogamp.newt.Window;
+@SuppressWarnings("serial")
public class AWTCanvas extends Canvas {
private GraphicsDevice device;
private GraphicsConfiguration chosen;
private AWTGraphicsConfiguration awtConfig;
-
+ private volatile JAWTWindow jawtWindow=null; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
private CapabilitiesChooser chooser=null;
private CapabilitiesImmutable capabilities;
@@ -77,12 +83,31 @@ public class AWTCanvas extends Canvas {
return awtConfig;
}
+ /**
+ * Overridden from Canvas to prevent the AWT's clearing of the
+ * canvas from interfering with the OpenGL rendering.
+ */
+ @Override
+ public void update(Graphics g) {
+ // paint(g);
+ }
+
+ /** Overridden to cause OpenGL rendering to be performed during
+ repaint cycles. Subclasses which override this method must call
+ super.paint() in their paint() method in order to function
+ properly.
+ */
+ @Override
+ public void paint(Graphics g) {
+ }
+
public boolean hasDeviceChanged() {
boolean res = displayConfigChanged;
displayConfigChanged=false;
return res;
}
+ @Override
public void addNotify() {
/**
@@ -95,8 +120,7 @@ public class AWTCanvas extends Canvas {
*/
awtConfig = chooseGraphicsConfiguration(capabilities, capabilities, chooser, device);
if(Window.DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Info: Created Config: "+awtConfig);
- e.printStackTrace();
+ System.err.println(getThreadName()+": AWTCanvas.addNotify.0: Created Config: "+awtConfig);
}
if(null==awtConfig) {
throw new NativeWindowException("Error: NULL AWTGraphicsConfiguration");
@@ -112,12 +136,32 @@ public class AWTCanvas extends Canvas {
// after native peer is valid: Windows
disableBackgroundErase();
+ {
+ jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
+ // trigger initialization cycle
+ jawtWindow.lockSurface();
+ jawtWindow.unlockSurface();
+ }
+
GraphicsConfiguration gc = super.getGraphicsConfiguration();
if(null!=gc) {
device = gc.getDevice();
}
+ if(Window.DEBUG_IMPLEMENTATION) {
+ System.err.println(getThreadName()+": AWTCanvas.addNotify.X");
+ }
+ }
+
+ public NativeWindow getNativeWindow() {
+ final JAWTWindow _jawtWindow = jawtWindow;
+ return (null != _jawtWindow) ? _jawtWindow : null;
+ }
+
+ public boolean isOffscreenLayerSurfaceEnabled() {
+ return null != jawtWindow ? jawtWindow.isOffscreenLayerSurfaceEnabled() : false;
}
+ @Override
public void removeNotify() {
try {
dispose();
@@ -127,6 +171,13 @@ public class AWTCanvas extends Canvas {
}
private void dispose() {
+ if( null != jawtWindow ) {
+ jawtWindow.destroy();
+ if(Window.DEBUG_IMPLEMENTATION) {
+ System.err.println(getThreadName()+": AWTCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
+ }
+ jawtWindow=null;
+ }
if(null != awtConfig) {
AbstractGraphicsDevice adevice = awtConfig.getNativeGraphicsConfiguration().getScreen().getDevice();
String adeviceMsg=null;
@@ -135,21 +186,24 @@ public class AWTCanvas extends Canvas {
}
boolean closed = adevice.close();
if(Window.DEBUG_IMPLEMENTATION) {
- System.err.println("AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
+ System.err.println(getThreadName()+": AWTCanvas.dispose(): closed GraphicsDevice: "+adeviceMsg+", result: "+closed);
}
}
}
+ private String getThreadName() { return Thread.currentThread().getName(); }
+
/**
* Overridden to choose a GraphicsConfiguration on a parent container's
* GraphicsDevice because both devices
*/
+ @Override
public GraphicsConfiguration getGraphicsConfiguration() {
/*
* Workaround for problems with Xinerama and java.awt.Component.checkGD
* when adding to a container on a different graphics device than the
* one that this Canvas is associated with.
- *
+ *
* GC will be null unless:
* - A native peer has assigned it. This means we have a native
* peer, and are already comitted to a graphics configuration.
@@ -163,7 +217,7 @@ public class AWTCanvas extends Canvas {
* chosen is only non-null on platforms where the GLDrawableFactory
* returns a non-null GraphicsConfiguration (in the GLCanvas
* constructor).
- *
+ *
* if gc is from this Canvas' native peer then it should equal chosen,
* otherwise it is from an ancestor component that this Canvas is being
* added to, and we go into this block.
@@ -173,21 +227,21 @@ public class AWTCanvas extends Canvas {
* Check for compatibility with gc. If they differ by only the
* device then return a new GCconfig with the super-class' GDevice
* (and presumably the same visual ID in Xinerama).
- *
+ *
*/
if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) {
/*
* Here we select a GraphicsConfiguration on the alternate
* device that is presumably identical to the chosen
* configuration, but on the other device.
- *
+ *
* Should really check to ensure that we select a configuration
* with the same X visual ID for Xinerama screens, otherwise the
* GLDrawable may have the wrong visual ID (I don't think this
* ever gets updated). May need to add a method to
* X11GLDrawableFactory to do this in a platform specific
* manner.
- *
+ *
* However, on platforms where we can actually get into this
* block, both devices should have the same visual list, and the
* same configuration should be selected here.
@@ -214,7 +268,7 @@ public class AWTCanvas extends Canvas {
chosen = compatible;
if( !config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) {
displayConfigChanged=true;
- }
+ }
awtConfig = config;
}
}
@@ -224,7 +278,7 @@ public class AWTCanvas extends Canvas {
* return the GC that was selected in the constructor (and might
* cause an exception in Component.checkGD when adding to a
* container, but in this case that would be the desired behavior).
- *
+ *
*/
return chosen;
} else if (gc == null) {
@@ -248,13 +302,13 @@ public class AWTCanvas extends Canvas {
CapabilitiesImmutable capsRequested,
CapabilitiesChooser chooser,
GraphicsDevice device) {
- final AbstractGraphicsScreen aScreen = null != device ?
+ final AbstractGraphicsScreen aScreen = null != device ?
AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT):
AWTGraphicsScreen.createDefault();
AWTGraphicsConfiguration config = (AWTGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, capsChosen.getClass()).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, aScreen);
+ chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (config == null) {
throw new NativeWindowException("Error: Couldn't fetch AWTGraphicsConfiguration");
}
@@ -272,10 +326,11 @@ public class AWTCanvas extends Canvas {
private void disableBackgroundErase() {
if (!disableBackgroundEraseInitialized) {
try {
- AccessController.doPrivileged(new PrivilegedAction() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
try {
- Class clazz = getToolkit().getClass();
+ Class<?> clazz = getToolkit().getClass();
while (clazz != null && disableBackgroundEraseMethod == null) {
try {
disableBackgroundEraseMethod =
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
index 942651187..4a7193306 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
@@ -28,72 +28,297 @@
package jogamp.newt.driver.awt;
-import javax.media.opengl.Threading;
+import java.awt.EventQueue;
+import javax.media.nativewindow.NativeWindowException;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.newt.util.EDTUtil;
+
import jogamp.newt.Debug;
public class AWTEDTUtil implements EDTUtil {
public static final boolean DEBUG = Debug.debug("EDT");
- private static AWTEDTUtil singletonMainThread = new AWTEDTUtil(); // one singleton MainThread
-
- public static AWTEDTUtil getSingleton() {
- return singletonMainThread;
- }
+ private final Object edtLock = new Object(); // locking the EDT start/stop state
+ private final ThreadGroup threadGroup;
+ private final String name;
+ private final Runnable dispatchMessages;
+ private NEDT nedt = null;
+ private int start_iter=0;
+ private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
- AWTEDTUtil() {
- // package private access ..
+ public AWTEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) {
+ this.threadGroup = tg;
+ this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
+ this.dispatchMessages=dispatchMessages;
+ this.nedt = new NEDT(threadGroup, name);
+ this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
}
+ @Override
final public long getPollPeriod() {
- return 0;
+ return pollPeriod;
}
+ @Override
final public void setPollPeriod(long ms) {
- // nop
+ pollPeriod = ms;
}
-
- final public void reset() {
- // nop AWT is always running
+
+ @Override
+ public final boolean start() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", on AWT-EDT "+EventQueue.isDispatchThread());
+ }
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": AWT-EDT reset - edt: "+nedt);
+ }
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
+ }
+ return invoke(true, nullTask);
}
- final public void start() {
- // nop AWT is always running
+ private final void startImpl() {
+ if(nedt.isAlive()) {
+ throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
+ }
+ start_iter++;
+ nedt.setName(name+start_iter);
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": AWT-EDT START - edt: "+nedt);
+ // Thread.dumpStack();
+ }
+ nedt.start();
}
+ @Override
final public boolean isCurrentThreadEDT() {
- return Threading.isToolkitThread();
+ return EventQueue.isDispatchThread();
}
+ @Override
+ public final boolean isCurrentThreadNEDT() {
+ return nedt == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadEDTorNEDT() {
+ return EventQueue.isDispatchThread() || nedt == Thread.currentThread();
+ }
+
+ @Override
final public boolean isRunning() {
- return true; // AWT is always running
+ return nedt.isRunning() ;
}
- final public void invokeStop(Runnable r) {
- invoke(true, r); // AWT is always running
+ @Override
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, true);
}
- final public void invoke(boolean wait, Runnable r) {
- if(r == null) {
- return;
+ @Override
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false);
+ }
+
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) {
+ Throwable throwable = null;
+ RunnableTask rTask = null;
+ final Object rTaskLock = new Object();
+ synchronized(rTaskLock) { // lock the optional task execution
+ synchronized(edtLock) { // lock the EDT status
+ if( nedt.shouldStop ) {
+ // drop task ..
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if(stop) {
+ nedt.shouldStop = true;
+ }
+ } else {
+ if( !nedt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+
+ if(null != task) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ AWTEDTExecutor.singleton.invoke(false, rTask);
+ }
+ }
+ }
+ if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ if(throwable instanceof NativeWindowException) {
+ throw (NativeWindowException)throwable;
+ }
+ throw new RuntimeException(throwable);
+ }
+ }
+ return true;
}
-
- Threading.invoke(wait, r, null);
}
- final public void waitUntilIdle() {
- // wait until previous events are processed, at least ..
+ @Override
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
+ synchronized(edtLock) {
+ _edt = nedt;
+ }
+ if(!_edt.isRunning || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) {
+ return false;
+ }
try {
- Threading.invoke(true, new Runnable() {
+ AWTEDTExecutor.singleton.invoke(true, new Runnable() {
+ @Override
public void run() { }
- }, null);
+ });
} catch (Exception e) { }
+ return true;
}
- final public void waitUntilStopped() {
- // nop: AWT is always running
+ @Override
+ final public boolean waitUntilStopped() {
+ synchronized(edtLock) {
+ if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) {
+ while( nedt.isRunning ) {
+ try {
+ edtLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
}
+
+ class NEDT extends Thread {
+ volatile boolean shouldStop = false;
+ volatile boolean isRunning = false;
+ Object sync = new Object();
+
+ public NEDT(ThreadGroup tg, String name) {
+ super(tg, name);
+ }
+
+ final public boolean isRunning() {
+ return isRunning && !shouldStop;
+ }
+
+ @Override
+ final public void start() throws IllegalThreadStateException {
+ isRunning = true;
+ super.start();
+ }
+
+ /**
+ * Utilizing locking only on tasks and its execution,
+ * not for event dispatching.
+ */
+ @Override
+ final public void run() {
+ if(DEBUG) {
+ System.err.println(getName()+": AWT-EDT run() START "+ getName());
+ }
+ RuntimeException error = null;
+ try {
+ do {
+ // event dispatch
+ if(!shouldStop) {
+ // EDT invoke thread is AWT-EDT,
+ // hence dispatching is required to run on AWT-EDT as well.
+ // Otherwise a deadlock may happen due to dispatched event's
+ // triggering a locking action.
+ AWTEDTExecutor.singleton.invoke(true, dispatchMessages);
+ }
+ // wait
+ synchronized(sync) {
+ if(!shouldStop) {
+ try {
+ sync.wait(pollPeriod);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } while(!shouldStop) ;
+ } catch (Throwable t) {
+ // handle errors ..
+ shouldStop = true;
+ if(t instanceof RuntimeException) {
+ error = (RuntimeException) t;
+ } else {
+ error = new RuntimeException("Within AWT-EDT", t);
+ }
+ } finally {
+ if(DEBUG) {
+ System.err.println(getName()+": AWT-EDT run() END "+ getName()+", "+error);
+ }
+ synchronized(edtLock) {
+ isRunning = false;
+ edtLock.notifyAll();
+ }
+ if(DEBUG) {
+ System.err.println(getName()+": AWT-EDT run() EXIT "+ getName()+", exception: "+error);
+ }
+ if(null!=error) {
+ throw error;
+ }
+ } // finally
+ } // run()
+ } // EventDispatchThread
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java b/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java
deleted file mode 100644
index a3c0281b1..000000000
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.awt;
-
-import java.awt.DisplayMode;
-
-import jogamp.newt.ScreenImpl;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
-import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
-
-public class AWTScreen extends ScreenImpl {
- public AWTScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice());
- }
-
- protected void setAWTGraphicsScreen(AWTGraphicsScreen s) {
- aScreen = s;
- }
-
- /**
- * Used by AWTWindow ..
- */
- @Override
- protected void updateVirtualScreenOriginAndSize() {
- super.updateVirtualScreenOriginAndSize();
- }
-
- protected void closeNativeImpl() { }
-
- protected int validateScreenIndex(int idx) {
- return idx; // pass through ...
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode();
- if(null != mode) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(mode.getWidth());
- virtualSize.setHeight(mode.getHeight());
- }
- }
-
-}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java
deleted file mode 100644
index 2b2fed545..000000000
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.awt;
-
-import java.awt.BorderLayout;
-import java.awt.Container;
-import java.awt.Frame;
-import java.awt.Insets;
-
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Point;
-
-import jogamp.newt.WindowImpl;
-
-import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
-import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
-import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
-import com.jogamp.newt.event.awt.AWTKeyAdapter;
-import com.jogamp.newt.event.awt.AWTMouseAdapter;
-import com.jogamp.newt.event.awt.AWTWindowAdapter;
-
-/** An implementation of the Newt Window class built using the
- AWT. This is provided for convenience of porting to platforms
- supporting Java SE. */
-
-public class AWTWindow extends WindowImpl {
-
- public AWTWindow() {
- this(null);
- }
-
- public static Class<?>[] getCustomConstructorArgumentTypes() {
- return new Class<?>[] { Container.class } ;
- }
-
- public AWTWindow(Container container) {
- super();
- this.container = container;
- if(container instanceof Frame) {
- frame = (Frame) container;
- }
- }
-
- private boolean owningFrame;
- private Container container = null;
- private Frame frame = null; // same instance as container, just for impl. convenience
- private AWTCanvas canvas;
-
- protected void requestFocusImpl(boolean reparented) {
- container.requestFocus();
- }
-
- @Override
- protected void setTitleImpl(final String title) {
- if (frame != null) {
- frame.setTitle(title);
- }
- }
-
- protected void createNativeImpl() {
- if(0!=getParentWindowHandle()) {
- throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
- }
-
- if(null==container) {
- frame = new Frame();
- container = frame;
- owningFrame=true;
- } else {
- owningFrame=false;
- defineSize(container.getWidth(), container.getHeight());
- definePosition(container.getX(), container.getY());
- }
- if(null!=frame) {
- frame.setTitle(getTitle());
- }
- container.setLayout(new BorderLayout());
- canvas = new AWTCanvas(capsRequested, AWTWindow.this.capabilitiesChooser);
-
- addWindowListener(new LocalWindowListener());
-
- new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here
- new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here
-
- // canvas.addComponentListener(listener);
- container.add(canvas, BorderLayout.CENTER);
- container.setSize(getWidth(), getHeight());
- container.setLocation(getX(), getY());
- new AWTWindowAdapter(this).addTo(container); // fwd all AWT Window events to here
-
- reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
- // throws exception if failed ..
-
- setWindowHandle(1); // just a marker ..
- }
-
- protected void closeNativeImpl() {
- setWindowHandle(0); // just a marker ..
- if(null!=container) {
- container.setVisible(false);
- container.remove(canvas);
- container.setEnabled(false);
- canvas.setEnabled(false);
- }
- if(owningFrame && null!=frame) {
- frame.dispose();
- owningFrame=false;
- frame = null;
- }
- }
-
- @Override
- public boolean hasDeviceChanged() {
- boolean res = canvas.hasDeviceChanged();
- if(res) {
- final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
- if (null == cfg) {
- throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
- }
- setGraphicsConfiguration(cfg);
-
- // propagate new info ..
- ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen());
- ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice());
-
- ((AWTScreen)getScreen()).updateVirtualScreenOriginAndSize();
- }
- return res;
- }
-
- protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) {
- Insets contInsets = container.getInsets();
- insets.setLeftWidth(contInsets.left);
- insets.setRightWidth(contInsets.right);
- insets.setTopHeight(contInsets.top);
- insets.setBottomHeight(contInsets.bottom);
- }
-
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=frame) {
- if(!container.isDisplayable()) {
- frame.setUndecorated(isUndecorated());
- } else {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("AWTWindow can't undecorate already created frame");
- }
- }
- }
-
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- container.setVisible(0 != ( FLAG_IS_VISIBLE & flags));
- }
-
- container.setLocation(x, y);
- Insets insets = container.getInsets();
- container.setSize(width + insets.left + insets.right,
- height + insets.top + insets.bottom);
-
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
- if( !hasDeviceChanged() ) {
- // oops ??
- final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration();
- if(null == cfg) {
- throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this);
- }
- setGraphicsConfiguration(cfg);
- }
- }
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
- }
-
- return true;
- }
-
- protected Point getLocationOnScreenImpl(int x, int y) {
- java.awt.Point ap = canvas.getLocationOnScreen();
- ap.translate(x, y);
- return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5));
- }
-
- @Override
- public Object getWrappedWindow() {
- return canvas;
- }
-
- class LocalWindowListener extends com.jogamp.newt.event.WindowAdapter {
- @Override
- public void windowMoved(com.jogamp.newt.event.WindowEvent e) {
- if(null!=container) {
- definePosition(container.getX(), container.getY());
- }
- }
- @Override
- public void windowResized(com.jogamp.newt.event.WindowEvent e) {
- if(null!=canvas) {
- defineSize(canvas.getWidth(), canvas.getHeight());
- }
- }
- }
-}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
index 166da5c1c..d9a4a48e5 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,20 +29,24 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.awt;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.util.EDTUtil;
import jogamp.newt.DisplayImpl;
-public class AWTDisplay extends DisplayImpl {
- public AWTDisplay() {
+public class DisplayDriver extends DisplayImpl {
+ public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
aDevice = AWTGraphicsDevice.createDefault();
}
@@ -51,18 +55,26 @@ public class AWTDisplay extends DisplayImpl {
aDevice = d;
}
- protected void closeNativeImpl() { }
-
@Override
- protected void createEDTUtil() {
+ protected EDTUtil createEDTUtil() {
+ final EDTUtil def;
if(NewtFactory.useEDT()) {
- edtUtil = AWTEDTUtil.getSingleton();
+ def = new AWTEDTUtil(Thread.currentThread().getThreadGroup(), "AWTDisplay-"+getFQName(), dispatchMessagesRunnable);
if(DEBUG) {
- System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName());
+ System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName());
}
+ } else {
+ def = null;
}
+ return def;
}
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+
+ @Override
protected void dispatchMessagesNative() { /* nop */ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
new file mode 100644
index 000000000..a4356707e
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.awt;
+
+import java.awt.DisplayMode;
+import java.awt.GraphicsDevice;
+
+import jogamp.newt.MonitorModeProps.Cache;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends ScreenImpl {
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice());
+ }
+
+ protected void setAWTGraphicsScreen(AWTGraphicsScreen s) {
+ aScreen = s;
+ }
+
+ /**
+ * Used by AWTWindow ..
+ */
+ @Override
+ protected void updateVirtualScreenOriginAndSize() {
+ super.updateVirtualScreenOriginAndSize();
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return idx; // pass through ...
+ }
+
+ private static MonitorMode getModeProps(Cache cache, DisplayMode mode) {
+ int rate = mode.getRefreshRate();
+ if( DisplayMode.REFRESH_RATE_UNKNOWN == rate ) {
+ rate = ScreenImpl.default_sm_rate;
+ }
+ int bpp = mode.getBitDepth();
+ if( DisplayMode.BIT_DEPTH_MULTI == bpp ) {
+ bpp= ScreenImpl.default_sm_bpp;
+ }
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = mode.getWidth();
+ props[i++] = mode.getHeight();
+ props[i++] = bpp;
+ props[i++] = rate * 100;
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ return MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ }
+
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(Cache cache) {
+ final GraphicsDevice awtGD = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice();
+ final DisplayMode[] awtModes = awtGD.getDisplayModes();
+ for(int i=0; i<awtModes.length; i++) {
+ getModeProps(cache, awtModes[i]);
+ }
+ final MonitorMode currentMode = getModeProps(cache, awtGD.getDisplayMode());
+
+ int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+ return null;
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+ return false;
+ }
+
+}
diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
new file mode 100644
index 000000000..9854524d9
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Insets;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.Point;
+
+import jogamp.nativewindow.awt.AWTMisc;
+import jogamp.newt.WindowImpl;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.newt.event.awt.AWTKeyAdapter;
+import com.jogamp.newt.event.awt.AWTMouseAdapter;
+import com.jogamp.newt.event.awt.AWTWindowAdapter;
+
+/** An implementation of the Newt Window class built using the
+ AWT. This is provided for convenience of porting to platforms
+ supporting Java SE. */
+
+public class WindowDriver extends WindowImpl {
+
+ public WindowDriver() {
+ this(null);
+ }
+
+ public static Class<?>[] getCustomConstructorArgumentTypes() {
+ return new Class<?>[] { Container.class } ;
+ }
+
+ public WindowDriver(Container container) {
+ super();
+ this.awtContainer = container;
+ if(container instanceof Frame) {
+ awtFrame = (Frame) container;
+ }
+ }
+
+ private boolean owningFrame;
+ private Container awtContainer = null;
+ /** same instance as container, just for impl. convenience */
+ private Frame awtFrame = null;
+ private AWTCanvas awtCanvas;
+
+ @Override
+ protected void requestFocusImpl(boolean reparented) {
+ awtContainer.requestFocus();
+ }
+
+ @Override
+ protected void setTitleImpl(final String title) {
+ if (awtFrame != null) {
+ awtFrame.setTitle(title);
+ }
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ if(0!=getParentWindowHandle()) {
+ throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
+ }
+
+ if(null==awtContainer) {
+ awtFrame = new Frame();
+ awtContainer = awtFrame;
+ owningFrame=true;
+ } else {
+ owningFrame=false;
+ defineSize(awtContainer.getWidth(), awtContainer.getHeight());
+ definePosition(awtContainer.getX(), awtContainer.getY());
+ }
+ if(null!=awtFrame) {
+ awtFrame.setTitle(getTitle());
+ }
+ awtContainer.setLayout(new BorderLayout());
+
+ if( null == awtCanvas ) {
+ awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser);
+
+ // canvas.addComponentListener(listener);
+ awtContainer.add(awtCanvas, BorderLayout.CENTER);
+
+ // via EDT ..
+ new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here
+ new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here
+
+ // direct w/o EDT
+ new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here
+ }
+
+ reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
+ // throws exception if failed ..
+
+ final NativeWindow nw = awtCanvas.getNativeWindow();
+ if( null != nw ) {
+ setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() );
+ setWindowHandle( nw.getWindowHandle() );
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ setWindowHandle(0);
+ if(null!=awtContainer) {
+ awtContainer.setVisible(false);
+ awtContainer.remove(awtCanvas);
+ awtContainer.setEnabled(false);
+ awtCanvas.setEnabled(false);
+ }
+ if(owningFrame && null!=awtFrame) {
+ awtFrame.dispose();
+ owningFrame=false;
+ }
+ awtCanvas = null;
+ awtFrame = null;
+ awtContainer = null;
+ }
+
+ @Override
+ public boolean hasDeviceChanged() {
+ boolean res = awtCanvas.hasDeviceChanged();
+ if(res) {
+ final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
+ if (null == cfg) {
+ throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
+ }
+ setGraphicsConfiguration(cfg);
+
+ // propagate new info ..
+ ((ScreenDriver)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen());
+ ((DisplayDriver)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice());
+
+ ((ScreenDriver)getScreen()).updateVirtualScreenOriginAndSize();
+ }
+ return res;
+ }
+
+ @Override
+ protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) {
+ final Insets contInsets = awtContainer.getInsets();
+ insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
+ }
+
+ private void setCanvasSizeImpl(int width, int height) {
+ final Dimension szClient = new Dimension(width, height);
+ final java.awt.Window awtWindow = AWTMisc.getWindow(awtCanvas);
+ final Container c= null != awtWindow ? awtWindow : awtContainer;
+ awtCanvas.setMinimumSize(szClient);
+ awtCanvas.setPreferredSize(szClient);
+ if(DEBUG_IMPLEMENTATION) {
+ final Insets insets = c.getInsets();
+ final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+ System.err.println(getThreadName()+": AWTWindow setCanvasSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+ }
+ awtCanvas.setSize(szClient);
+ awtCanvas.invalidate();
+ if(null != awtWindow) {
+ awtWindow.pack();
+ } else {
+ awtContainer.validate();
+ }
+ }
+ private void setFrameSizeImpl(int width, int height) {
+ final Insets insets = awtContainer.getInsets();
+ final Dimension szContainer = new Dimension(width + insets.left + insets.right,
+ height + insets.top + insets.bottom);
+ if(DEBUG_IMPLEMENTATION) {
+ final Dimension szClient = new Dimension(width, height);
+ System.err.println(getThreadName()+": AWTWindow setFrameSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
+ }
+ awtContainer.setSize(szContainer);
+ awtCanvas.invalidate();
+ awtContainer.validate();
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
+ getReconfigureFlagsAsString(null, flags));
+ }
+ if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=awtFrame) {
+ if(!awtContainer.isDisplayable()) {
+ awtFrame.setUndecorated(isUndecorated());
+ } else {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println(getThreadName()+": AWTWindow can't undecorate already created frame");
+ }
+ }
+ }
+
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
+ if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
+ setCanvasSizeImpl(width, height);
+ awtContainer.setVisible( true );
+ } else {
+ awtContainer.setVisible( false );
+ }
+ } else if( awtCanvas.getWidth() != width || awtCanvas.getHeight() != height ) {
+ if( Platform.OSType.MACOS == Platform.getOSType() && awtCanvas.isOffscreenLayerSurfaceEnabled() ) {
+ setFrameSizeImpl(width, height);
+ } else {
+ setCanvasSizeImpl(width, height);
+ }
+ }
+ defineSize(width, height); // we are on AWT-EDT .. change values immediately
+
+ if( awtContainer.getX() != x || awtContainer.getY() != y ) {
+ awtContainer.setLocation(x, y);
+ }
+
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
+ if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
+ if( !hasDeviceChanged() ) {
+ // oops ??
+ final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
+ if(null == cfg) {
+ throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this);
+ }
+ setGraphicsConfiguration(cfg);
+ }
+ }
+ visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+ }
+
+ return true;
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(int x, int y) {
+ java.awt.Point ap = awtCanvas.getLocationOnScreen();
+ ap.translate(x, y);
+ return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5));
+ }
+
+ @Override
+ public NativeSurface getWrappedSurface() {
+ return ( null != awtCanvas ) ? awtCanvas.getNativeWindow() : null;
+ }
+
+ class LocalWindowListener implements com.jogamp.newt.event.WindowListener {
+ @Override
+ public void windowMoved(com.jogamp.newt.event.WindowEvent e) {
+ if(null!=awtContainer) {
+ WindowDriver.this.positionChanged(false, awtContainer.getX(), awtContainer.getY());
+ }
+ }
+ @Override
+ public void windowResized(com.jogamp.newt.event.WindowEvent e) {
+ if(null!=awtCanvas) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window Resized: "+awtCanvas);
+ }
+ WindowDriver.this.sizeChanged(false, awtCanvas.getWidth(), awtCanvas.getHeight(), true);
+ WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());
+ }
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ WindowDriver.this.windowDestroyNotify(false);
+ }
+ @Override
+ public void windowDestroyed(WindowEvent e) {
+ // Not fwd by AWTWindowAdapter, synthesized by NEWT
+ }
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ WindowDriver.this.focusChanged(false, true);
+ }
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ WindowDriver.this.focusChanged(false, false);
+ }
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ if(null!=awtCanvas) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window Repaint: "+awtCanvas);
+ }
+ WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight());
+ }
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
index f90c62ff4..d1b30f7cc 100644
--- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Display.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,10 +29,10 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
-package jogamp.newt.driver.broadcom.egl;
+package jogamp.newt.driver.bcm.egl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
@@ -42,12 +42,12 @@ import jogamp.opengl.egl.EGL;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-public class Display extends jogamp.newt.DisplayImpl {
+public class DisplayDriver extends jogamp.newt.DisplayImpl {
static {
NEWTJNILibLoader.loadNEWT();
- if (!Window.initIDs()) {
+ if (!WindowDriver.initIDs()) {
throw new NativeWindowException("Failed to initialize BCEGL Window jmethodIDs");
}
}
@@ -57,23 +57,27 @@ public class Display extends jogamp.newt.DisplayImpl {
}
- public Display() {
+ public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
- long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight);
+ final long handle = CreateDisplay(ScreenDriver.fixedWidth, ScreenDriver.fixedHeight);
if (handle == EGL.EGL_NO_DISPLAY) {
throw new NativeWindowException("BC EGL CreateDisplay failed");
}
- aDevice = new EGLGraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null);
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
DestroyDisplay(aDevice.getHandle());
}
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
// n/a .. DispatchMessages();
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
new file mode 100644
index 000000000..d3231557f
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2012 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.bcm.egl;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends jogamp.newt.ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = fixedWidth; // FIXME
+ props[i++] = fixedHeight; // FIXME
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = fixedWidth; // FIXME rotated viewport width
+ props[i++] = fixedHeight; // FIXME rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+ vOriginSize.set(0, 0, fixedWidth, fixedHeight); // FIXME
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ static final int fixedWidth = 1920; // FIXME
+ static final int fixedHeight = 1080; // FIXME
+}
+
diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
index ed1d0511a..39f168e0f 100644
--- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,36 +29,38 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
-package jogamp.newt.driver.broadcom.egl;
+package jogamp.newt.driver.bcm.egl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import javax.media.opengl.GLCapabilitiesImmutable;
import jogamp.opengl.egl.EGLGraphicsConfiguration;
-public class Window extends jogamp.newt.WindowImpl {
+public class WindowDriver extends jogamp.newt.WindowImpl {
static {
- Display.initSingleton();
+ DisplayDriver.initSingleton();
}
- public Window() {
+ public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
}
- // query a good configuration, however chose the final one by the native queried egl-cfg-id
+ // query a good configuration, however chose the final one by the native queried egl-cfg-id
// after creation at {@link #windowCreated(int, int, int)}.
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
@@ -71,12 +73,14 @@ public class Window extends jogamp.newt.WindowImpl {
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose) {
CloseWindow(getDisplayHandle(), windowHandleClose);
}
}
+ @Override
protected void requestFocusImpl(boolean reparented) { }
protected void setSizeImpl(int width, int height) {
@@ -88,8 +92,9 @@ public class Window extends jogamp.newt.WindowImpl {
}
}
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if(0!=getWindowHandle()) {
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ if(0!=getWindowHandle()) {
if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
if( 0 != ( FLAG_IS_FULLSCREEN & flags) ) {
// n/a in BroadcomEGL
@@ -109,19 +114,21 @@ public class Window extends jogamp.newt.WindowImpl {
if(x>=0 || y>=0) {
System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL");
}
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
return true;
}
+ @Override
protected Point getLocationOnScreenImpl(int x, int y) {
return new Point(x,y);
}
+ @Override
protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ // nop ..
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
new file mode 100644
index 000000000..178bb70f7
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright 2012 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.bcm.vc.iv;
+
+import java.net.URLConnection;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+import jogamp.newt.DisplayImpl;
+import jogamp.newt.NEWTJNILibLoader;
+import jogamp.newt.PointerIconImpl;
+import jogamp.newt.driver.linux.LinuxMouseTracker;
+import jogamp.opengl.egl.EGL;
+import jogamp.opengl.egl.EGLDisplayUtil;
+
+public class DisplayDriver extends DisplayImpl {
+ static final PNGPixelRect defaultPointerIconImage;
+
+ static {
+ NEWTJNILibLoader.loadNEWT();
+
+ if (!DisplayDriver.initIDs()) {
+ throw new NativeWindowException("Failed to initialize bcm.vc.iv Display jmethodIDs");
+ }
+ if (!ScreenDriver.initIDs()) {
+ throw new NativeWindowException("Failed to initialize bcm.vc.iv Screen jmethodIDs");
+ }
+ if (!WindowDriver.initIDs()) {
+ throw new NativeWindowException("Failed to initialize bcm.vc.iv Window jmethodIDs");
+ }
+
+ PNGPixelRect image = null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(DisplayDriver.class, new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultPointerIconImage = image;
+ }
+
+ public static void initSingleton() {
+ // just exist to ensure static init has been run
+ }
+
+
+ public DisplayDriver() {
+ bcmHandle = 0;
+ activePointerIcon = 0;
+ activePointerIconVisible = false;
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ // FIXME: map name to EGL_*_DISPLAY
+ bcmHandle = OpenBCMDisplay0();
+ aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
+
+ defaultPointerIcon = (PointerIconImpl) createPointerIcon(defaultPointerIconImage, 0, 0);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.createDefault: "+defaultPointerIcon);
+ }
+ if( null != defaultPointerIcon ) {
+ final LinuxMouseTracker lmt = LinuxMouseTracker.getSingleton();
+ setPointerIconActive(defaultPointerIcon.getHandle(), lmt.getLastX(), lmt.getLastY());
+ }
+ }
+ private PointerIconImpl defaultPointerIcon = null;
+
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ CloseBCMDisplay0(bcmHandle);
+ bcmHandle = 0;
+ }
+
+ /* pp */ final long getBCMHandle() { return bcmHandle; }
+
+ @Override
+ protected void dispatchMessagesNative() {
+ DispatchMessages0();
+ }
+
+ // @Override
+ // public final PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return CreatePointerIcon(bcmHandle, pixels, width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) {
+ DestroyPointerIcon0(piHandle);
+ }
+
+ /* pp */ void setPointerIconActive(long piHandle, final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.set.0: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"] -> "+toHexString(piHandle));
+ }
+ if( 0 != activePointerIcon && activePointerIconVisible ) {
+ SetPointerIcon0(bcmHandle, activePointerIcon, false, x, y);
+ }
+ if( 0 == piHandle && null != defaultPointerIcon ) {
+ piHandle = defaultPointerIcon.getHandle();
+ }
+ if( 0 != piHandle ) {
+ SetPointerIcon0(bcmHandle, piHandle, true, x, y);
+ activePointerIconVisible = true;
+ } else {
+ activePointerIconVisible = false;
+ }
+ activePointerIcon = piHandle;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.set.X: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"]");
+ }
+ }
+ }
+ /* pp */ void setActivePointerIconVisible(final boolean visible, final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.visible: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"] -> visible "+visible);
+ }
+ if( activePointerIconVisible != visible ) {
+ if( 0 != activePointerIcon ) {
+ SetPointerIcon0(bcmHandle, activePointerIcon, visible, x, y);
+ }
+ activePointerIconVisible = visible;
+ }
+ }
+ }
+ /* pp */ void moveActivePointerIcon(final int x, final int y) {
+ synchronized(pointerIconSync) {
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("Display.PointerIcon.move: active ["+toHexString(activePointerIcon)+", visible "+activePointerIconVisible+"], "+x+"/"+y);
+ }
+ if( 0 != activePointerIcon && activePointerIconVisible ) {
+ MovePointerIcon0(activePointerIcon, x, y);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ protected static native boolean initIDs();
+ private static native long OpenBCMDisplay0();
+ private static native void CloseBCMDisplay0(long handle);
+
+ private static long CreatePointerIcon(long bcmHandle, Buffer pixels, int width, int height, int hotX, int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return CreatePointerIcon0(pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
+ }
+ private static native long CreatePointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+ private static native void DestroyPointerIcon0(long handle);
+ private static native void SetPointerIcon0(long bcmHandle, long handle, boolean enable, int x, int y);
+ private static native void MovePointerIcon0(long handle, int x, int y);
+
+ private static native void DispatchMessages0();
+
+ private long bcmHandle;
+ private long activePointerIcon;
+ private boolean activePointerIconVisible;
+ private final Object pointerIconSync = new Object();
+}
+
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
new file mode 100644
index 000000000..dc2a8459a
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright 2012 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.bcm.vc.iv;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.util.Rectangle;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+public class ScreenDriver extends ScreenImpl {
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ initNative();
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = cachedWidth; // rotated viewport width
+ props[i++] = cachedWidth; // rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+ vOriginSize.set(0, 0, cachedWidth, cachedHeight);
+ }
+
+ /** Called from {@link #initNative()}. */
+ protected void setScreenSize(int width, int height) {
+ cachedWidth = width;
+ cachedHeight = height;
+ }
+
+ private static int cachedWidth = 0;
+ private static int cachedHeight = 0;
+
+ protected static native boolean initIDs();
+ protected native void initNative();
+}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
new file mode 100644
index 000000000..c3cb8a84c
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/WindowDriver.java
@@ -0,0 +1,215 @@
+/**
+ * Copyright 2012 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.bcm.vc.iv;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.Capabilities;
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.Point;
+
+import com.jogamp.common.util.IntBitfield;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.newt.event.MouseEvent;
+
+import jogamp.newt.PointerIconImpl;
+import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.linux.LinuxEventDeviceTracker;
+import jogamp.newt.driver.linux.LinuxMouseTracker;
+import jogamp.opengl.egl.EGLDisplayUtil;
+
+public class WindowDriver extends WindowImpl {
+ private static final String WINDOW_CLASS_NAME = "NewtWindow";
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public WindowDriver() {
+ linuxMouseTracker = LinuxMouseTracker.getSingleton();
+ linuxEventDeviceTracker = LinuxEventDeviceTracker.getSingleton();
+ layer = -1;
+ nativeWindowHandle = 0;
+ windowHandleClose = 0;
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ if(0!=getParentWindowHandle()) {
+ throw new RuntimeException("Window parenting not supported (yet)");
+ }
+ synchronized( layerSync ) {
+ if( layerCount >= MAX_LAYERS ) {
+ throw new RuntimeException("Max windows reached: "+layerCount+" ( "+MAX_LAYERS+" )");
+ }
+ for(int i=0; 0 > layer && i<MAX_LAYERS; i++) {
+ if( !usedLayers.get(nextLayer) ) {
+ layer = nextLayer;
+ usedLayers.put(layer, true);
+ layerCount++;
+ }
+ nextLayer++;
+ if( MAX_LAYERS == nextLayer ) {
+ nextLayer=0;
+ }
+ }
+ // System.err.println("XXX.Open capacity "+usedLayers.capacity()+", count "+usedLayers.getBitCount());
+ }
+ if( 0 > layer ) {
+ throw new InternalError("Could not find a free layer: count "+layerCount+", max "+MAX_LAYERS);
+ }
+ final ScreenDriver screen = (ScreenDriver) getScreen();
+ final DisplayDriver display = (DisplayDriver) screen.getDisplay();
+
+ // Create own screen/device resource instance allowing independent ownership,
+ // while still utilizing shared EGL resources.
+ final AbstractGraphicsScreen aScreen = screen.getGraphicsScreen();
+ final EGLGraphicsDevice aDevice = (EGLGraphicsDevice) aScreen.getDevice();
+ final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(aDevice.getNativeDisplayID(), aDevice.getConnection(), aDevice.getUnitID());
+ eglDevice.open();
+ final DefaultGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aScreen.getIndex());
+
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, eglScreen, VisualIDHolder.VID_UNDEFINED);
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ final Capabilities chosenCaps = (Capabilities) cfg.getChosenCapabilities();
+ // FIXME: Pass along opaque flag, since EGL doesn't determine it
+ if(capsRequested.isBackgroundOpaque() != chosenCaps.isBackgroundOpaque()) {
+ chosenCaps.setBackgroundOpaque(capsRequested.isBackgroundOpaque());
+ }
+ setGraphicsConfiguration(cfg);
+ nativeWindowHandle = CreateWindow0(display.getBCMHandle(), layer, getX(), getY(), getWidth(), getHeight(),
+ chosenCaps.isBackgroundOpaque(), chosenCaps.getAlphaBits());
+ if (nativeWindowHandle == 0) {
+ throw new NativeWindowException("Error creating egl window: "+cfg);
+ }
+ setWindowHandle(nativeWindowHandle);
+ if (0 == getWindowHandle()) {
+ throw new NativeWindowException("Error native Window Handle is null");
+ }
+ windowHandleClose = nativeWindowHandle;
+
+ addWindowListener(linuxEventDeviceTracker);
+ addWindowListener(linuxMouseTracker);
+ focusChanged(false, true);
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getGraphicsConfiguration().getScreen().getDevice();
+
+ removeWindowListener(linuxMouseTracker);
+ removeWindowListener(linuxEventDeviceTracker);
+
+ if(0!=windowHandleClose) {
+ CloseWindow0(display.getBCMHandle(), windowHandleClose);
+ }
+
+ eglDevice.close();
+
+ synchronized( layerSync ) {
+ usedLayers.put(layer, false);
+ layerCount--;
+ layer = -1;
+ // System.err.println("XXX.Close capacity "+usedLayers.capacity()+", count "+usedLayers.getBitCount());
+ }
+ }
+
+ @Override
+ protected void requestFocusImpl(boolean reparented) {
+ focusChanged(false, true);
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
+ reconfigure0(nativeWindowHandle, x, y, width, height, flags);
+ return true;
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(int x, int y) {
+ return new Point(x,y);
+ }
+
+ @Override
+ protected void updateInsetsImpl(Insets insets) {
+ // nop ..
+ }
+
+ @Override
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
+ if( MouseEvent.EVENT_MOUSE_MOVED == eventType ) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.moveActivePointerIcon(x, y);
+ }
+ super.sendMouseEvent(eventType, modifiers, x, y, button, rotation);
+ }
+
+ @Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.setPointerIconActive(null != pi ? pi.validatedHandle() : 0, linuxMouseTracker.getLastX(), linuxMouseTracker.getLastY());
+ }
+
+ @Override
+ protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ display.setActivePointerIconVisible(pointerVisible, linuxMouseTracker.getLastX(), linuxMouseTracker.getLastY());
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ private final LinuxMouseTracker linuxMouseTracker;
+ private final LinuxEventDeviceTracker linuxEventDeviceTracker;
+
+ protected static native boolean initIDs();
+ private native long CreateWindow0(long bcmDisplay, int layer, int x, int y, int width, int height, boolean opaque, int alphaBits);
+ private native void CloseWindow0(long bcmDisplay, long eglWindowHandle);
+ private native void reconfigure0(long eglWindowHandle, int x, int y, int width, int height, int flags);
+
+ private int layer;
+ private long nativeWindowHandle;
+ private long windowHandleClose;
+
+ private static int nextLayer = 0;
+ private static int layerCount = 0;
+ private static final int MAX_LAYERS = 32;
+ private static final IntBitfield usedLayers = new IntBitfield(MAX_LAYERS);
+ private static final Object layerSync = new Object();
+}
diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java
deleted file mode 100644
index 0544bc06c..000000000
--- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2012 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.broadcom.egl;
-
-import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-public class Screen extends jogamp.newt.ScreenImpl {
-
- static {
- Display.initSingleton();
- }
-
-
- public Screen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() { }
-
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(fixedWidth); // FIXME
- virtualSize.setHeight(fixedHeight); // FIXME
- }
-
- //----------------------------------------------------------------------
- // Internals only
- //
-
- static final int fixedWidth = 1920; // FIXME
- static final int fixedHeight = 1080; // FIXME
-}
-
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
index 20e151eb3..cc435540f 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Display.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
@@ -36,16 +37,16 @@ package jogamp.newt.driver.intel.gdl;
import jogamp.newt.*;
import javax.media.nativewindow.*;
-public class Display extends jogamp.newt.DisplayImpl {
+public class DisplayDriver extends jogamp.newt.DisplayImpl {
static int initCounter = 0;
static {
NEWTJNILibLoader.loadNEWT();
- if (!Screen.initIDs()) {
+ if (!ScreenDriver.initIDs()) {
throw new NativeWindowException("Failed to initialize GDL Screen jmethodIDs");
}
- if (!Window.initIDs()) {
+ if (!WindowDriver.initIDs()) {
throw new NativeWindowException("Failed to initialize GDL Window jmethodIDs");
}
}
@@ -55,11 +56,12 @@ public class Display extends jogamp.newt.DisplayImpl {
}
- public Display() {
+ public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
- synchronized(Display.class) {
+ synchronized(DisplayDriver.class) {
if(0==initCounter) {
displayHandle = CreateDisplay();
if(0==displayHandle) {
@@ -71,11 +73,12 @@ public class Display extends jogamp.newt.DisplayImpl {
aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle);
}
- protected void closeNativeImpl() {
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
if(0==displayHandle) {
throw new NativeWindowException("displayHandle null; initCnt "+initCounter);
}
- synchronized(Display.class) {
+ synchronized(DisplayDriver.class) {
if(initCounter>0) {
initCounter--;
if(0==initCounter) {
@@ -83,22 +86,24 @@ public class Display extends jogamp.newt.DisplayImpl {
}
}
}
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
if(0!=displayHandle) {
DispatchMessages(displayHandle, focusedWindow);
}
}
- protected void setFocus(Window focus) {
+ protected void setFocus(WindowDriver focus) {
focusedWindow = focus;
}
private long displayHandle = 0;
- private Window focusedWindow = null;
+ private WindowDriver focusedWindow = null;
private native long CreateDisplay();
private native void DestroyDisplay(long displayHandle);
- private native void DispatchMessages(long displayHandle, Window focusedWindow);
+ private native void DispatchMessages(long displayHandle, WindowDriver focusedWindow);
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
index 66ad1c691..44802e348 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,44 +29,87 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
-public class Screen extends jogamp.newt.ScreenImpl {
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends jogamp.newt.ScreenImpl {
static {
- Display.initSingleton();
+ DisplayDriver.initSingleton();
}
- public Screen() {
+ public ScreenDriver() {
}
+ @Override
protected void createNativeImpl() {
AbstractGraphicsDevice adevice = getDisplay().getGraphicsDevice();
GetScreenInfo(adevice.getHandle(), screen_idx);
aScreen = new DefaultGraphicsScreen(adevice, screen_idx);
}
+ @Override
protected void closeNativeImpl() { }
+ @Override
protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = cachedWidth; // rotated viewport width
+ props[i++] = cachedWidth; // rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
}
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(cachedWidth);
- virtualSize.setHeight(cachedHeight);
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+ vOriginSize.set(0, 0, cachedWidth, cachedHeight);
}
-
+
//----------------------------------------------------------------------
// Internals only
//
@@ -78,7 +122,7 @@ public class Screen extends jogamp.newt.ScreenImpl {
cachedWidth = width;
cachedHeight = height;
}
-
+
private static int cachedWidth = 0;
private static int cachedHeight = 0;
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
index 09e0e3016..0e96c65d0 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.intel.gdl;
@@ -37,16 +38,17 @@ import javax.media.nativewindow.*;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
-public class Window extends jogamp.newt.WindowImpl {
+public class WindowDriver extends jogamp.newt.WindowImpl {
static {
- Display.initSingleton();
+ DisplayDriver.initSingleton();
}
- public Window() {
+ public WindowDriver() {
}
static long nextWindowHandle = 1;
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new NativeWindowException("GDL Window does not support window parenting");
@@ -54,14 +56,14 @@ public class Window extends jogamp.newt.WindowImpl {
final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen();
final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, aScreen);
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice, capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
- synchronized(Window.class) {
+ synchronized(WindowDriver.class) {
setWindowHandle(nextWindowHandle++); // just a marker
surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), getX(), getY(), getWidth(), getHeight());
@@ -71,18 +73,20 @@ public class Window extends jogamp.newt.WindowImpl {
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=surfaceHandle) {
- synchronized(Window.class) {
+ synchronized(WindowDriver.class) {
CloseSurface(getDisplayHandle(), surfaceHandle);
}
surfaceHandle = 0;
- ((Display)getScreen().getDisplay()).setFocus(null);
+ ((DisplayDriver)getScreen().getDisplay()).setFocus(null);
}
}
+ @Override
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- Screen screen = (Screen) getScreen();
+ ScreenDriver screen = (ScreenDriver) getScreen();
if(width>screen.getWidth()) {
width=screen.getWidth();
@@ -103,16 +107,17 @@ public class Window extends jogamp.newt.WindowImpl {
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
if(0 != ( FLAG_IS_VISIBLE & flags)) {
- ((Display)getScreen().getDisplay()).setFocus(this);
+ ((DisplayDriver)getScreen().getDisplay()).setFocus(this);
}
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
return true;
}
+ @Override
protected void requestFocusImpl(boolean reparented) {
- ((Display)getScreen().getDisplay()).setFocus(this);
+ ((DisplayDriver)getScreen().getDisplay()).setFocus(this);
}
@Override
@@ -120,14 +125,16 @@ public class Window extends jogamp.newt.WindowImpl {
return surfaceHandle;
}
+ @Override
protected Point getLocationOnScreenImpl(int x, int y) {
return new Point(x,y);
}
+ @Override
protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ // nop ..
}
-
+
//----------------------------------------------------------------------
// Internals only
//
diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
index 73bbe0b5b..6c706148a 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/KDDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.kd;
@@ -42,15 +42,12 @@ import jogamp.newt.NEWTJNILibLoader;
import jogamp.opengl.egl.EGL;
import jogamp.opengl.egl.EGLDisplayUtil;
-import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-
-public class KDDisplay extends DisplayImpl {
-
+public class DisplayDriver extends DisplayImpl {
static {
NEWTJNILibLoader.loadNEWT();
- if (!KDWindow.initIDs()) {
- throw new NativeWindowException("Failed to initialize KDWindow jmethodIDs");
+ if (!WindowDriver.initIDs()) {
+ throw new NativeWindowException("Failed to initialize kd.Window jmethodIDs");
}
}
@@ -59,27 +56,22 @@ public class KDDisplay extends DisplayImpl {
}
- public KDDisplay() {
+ public DisplayDriver() {
}
+ @Override
protected void createNativeImpl() {
// FIXME: map name to EGL_*_DISPLAY
- long handle = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (handle == EGL.EGL_NO_DISPLAY) {
- throw new NativeWindowException("eglGetDisplay failed");
- }
- if (!EGLDisplayUtil.eglInitialize(handle, null, null)) {
- throw new NativeWindowException("eglInitialize failed");
- }
- aDevice = new EGLGraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
+ aDevice.open();
}
- protected void closeNativeImpl() {
- if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
- EGLDisplayUtil.eglTerminate(aDevice.getHandle());
- }
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ aDevice.close();
}
+ @Override
protected void dispatchMessagesNative() {
DispatchMessages();
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java b/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java
deleted file mode 100644
index ee3475880..000000000
--- a/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2012 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.kd;
-
-import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import jogamp.newt.ScreenImpl;
-
-public class KDScreen extends ScreenImpl {
- static {
- KDDisplay.initSingleton();
- }
-
- public KDScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() { }
-
- protected int validateScreenIndex(int idx) {
- return 0; // only one screen available
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(cachedWidth);
- virtualSize.setHeight(cachedHeight);
- }
-
- protected void sizeChanged(int w, int h) {
- cachedWidth = w;
- cachedHeight = h;
- }
-
- private static int cachedWidth = 0;
- private static int cachedHeight = 0;
-}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
new file mode 100644
index 000000000..9ebe2629a
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2012 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.kd;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.util.Rectangle;
+
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+public class ScreenDriver extends ScreenImpl {
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // only one screen available
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = cachedWidth; // width
+ props[i++] = cachedHeight; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // FIXME
+ props[i++] = ScreenImpl.default_sm_rate * 100; // FIXME
+ props[i++] = 0; // flags
+ props[i++] = 0; // mode_idx
+ props[i++] = 0; // rotation
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+
+ props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 - MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES];
+ i = 0;
+ props[i++] = props.length;
+ props[i++] = 0; // crt_idx
+ props[i++] = ScreenImpl.default_sm_widthmm; // FIXME
+ props[i++] = ScreenImpl.default_sm_heightmm; // FIXME
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = cachedWidth; // rotated viewport width
+ props[i++] = cachedWidth; // rotated viewport height
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, cache.monitorModes, currentMode, props, 0);
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return monitor.getSupportedModes().get(0);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return false;
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+ vOriginSize.set(0, 0, cachedWidth, cachedHeight);
+ }
+
+ protected void sizeChanged(int w, int h) {
+ cachedWidth = w;
+ cachedHeight = h;
+ }
+
+ private static int cachedWidth = 0;
+ private static int cachedHeight = 0;
+}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
index d34ffd593..158e6ab2f 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,7 +29,7 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.kd;
@@ -37,6 +37,8 @@ package jogamp.newt.driver.kd;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.Point;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -44,33 +46,35 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import jogamp.newt.WindowImpl;
import jogamp.opengl.egl.EGLGraphicsConfiguration;
-public class KDWindow extends WindowImpl {
+public class WindowDriver extends WindowImpl {
private static final String WINDOW_CLASS_NAME = "NewtWindow";
static {
- KDDisplay.initSingleton();
+ DisplayDriver.initSingleton();
}
- public KDWindow() {
+ public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
if(0!=getParentWindowHandle()) {
throw new RuntimeException("Window parenting not supported (yet)");
}
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities();
- int[] eglAttribs = EGLGraphicsConfiguration.GLCapabilities2AttribList(eglCaps);
+ int eglConfigID = eglCaps.getVisualID(VIDType.EGL_CONFIG);
+ long eglConfig = EGLGraphicsConfiguration.EGLConfigId2EGLConfig(getDisplayHandle(), eglConfigID);
- eglWindowHandle = CreateWindow(getDisplayHandle(), eglAttribs);
+ eglWindowHandle = CreateWindow(getDisplayHandle(), eglConfig);
if (eglWindowHandle == 0) {
- throw new NativeWindowException("Error creating egl window: "+cfg);
+ throw new NativeWindowException("Error creating egl window: "+cfg+", eglConfigID "+eglConfigID+", eglConfig 0x"+Long.toHexString(eglConfig));
}
setVisible0(eglWindowHandle, false);
setWindowHandle(RealizeWindow(eglWindowHandle));
@@ -80,6 +84,7 @@ public class KDWindow extends WindowImpl {
windowHandleClose = eglWindowHandle;
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose) {
CloseWindow(windowHandleClose, windowUserData);
@@ -87,14 +92,16 @@ public class KDWindow extends WindowImpl {
}
}
+ @Override
protected void requestFocusImpl(boolean reparented) { }
+ @Override
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
setVisible0(eglWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags));
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
if(0!=eglWindowHandle) {
if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ;
@@ -114,28 +121,30 @@ public class KDWindow extends WindowImpl {
System.err.println("setPosition n/a in KD");
}
}
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
-
+
return true;
}
+ @Override
protected Point getLocationOnScreenImpl(int x, int y) {
return new Point(x,y);
}
+ @Override
protected void updateInsetsImpl(Insets insets) {
- // nop ..
+ // nop ..
}
-
+
//----------------------------------------------------------------------
// Internals only
//
protected static native boolean initIDs();
- private native long CreateWindow(long displayHandle, int[] attributes);
+ private native long CreateWindow(long displayHandle, long eglConfig);
private native long RealizeWindow(long eglWindowHandle);
private native int CloseWindow(long eglWindowHandle, long userData);
private native void setVisible0(long eglWindowHandle, boolean visible);
@@ -149,7 +158,7 @@ public class KDWindow extends WindowImpl {
@Override
protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
if(isFullscreen()) {
- ((KDScreen)getScreen()).sizeChanged(getWidth(), getHeight());
+ ((ScreenDriver)getScreen()).sizeChanged(getWidth(), getHeight());
}
super.sizeChanged(defer, newWidth, newHeight, force);
}
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
new file mode 100644
index 000000000..b7c86a26d
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxEventDeviceTracker.java
@@ -0,0 +1,959 @@
+/**
+ * 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.linux;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Integer;
+import java.lang.Runnable;
+import java.lang.String;
+import java.lang.Thread;
+import java.nio.ByteBuffer;
+
+import jogamp.newt.WindowImpl;
+
+import com.jogamp.common.nio.StructAccessor;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.newt.event.KeyEvent;
+
+/**
+ * Experimental native event device tracker thread for GNU/Linux
+ * just reading <code>/dev/input/event*</code>
+ * within it's own polling thread.
+ */
+
+public class LinuxEventDeviceTracker implements WindowListener {
+
+ private static final LinuxEventDeviceTracker ledt;
+
+
+ static {
+ ledt = new LinuxEventDeviceTracker();
+ final Thread t = new Thread(ledt.eventDeviceManager, "NEWT-LinuxEventDeviceManager");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static LinuxEventDeviceTracker getSingleton() {
+ return ledt;
+ }
+
+ private WindowImpl focusedWindow = null;
+ private EventDeviceManager eventDeviceManager = new EventDeviceManager();
+
+ /*
+ The devices are in /dev/input:
+
+ crw-r--r-- 1 root root 13, 64 Apr 1 10:49 event0
+ crw-r--r-- 1 root root 13, 65 Apr 1 10:50 event1
+ crw-r--r-- 1 root root 13, 66 Apr 1 10:50 event2
+ crw-r--r-- 1 root root 13, 67 Apr 1 10:50 event3
+ ...
+
+ And so on up to event31.
+ */
+ private EventDevicePoller[] eventDevicePollers = new EventDevicePoller[32];
+
+ @Override
+ public void windowResized(WindowEvent e) { }
+
+ @Override
+ public void windowMoved(WindowEvent e) { }
+
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ @Override
+ public void windowDestroyed(WindowEvent e) { }
+
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ Object s = e.getSource();
+ if(s instanceof WindowImpl) {
+ focusedWindow = (WindowImpl) s;
+ }
+ }
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ public static void main(String[] args ){
+ System.setProperty("newt.debug.Window.KeyEvent", "true");
+ LinuxEventDeviceTracker.getSingleton();
+ try {
+ while(true) {
+ Thread.sleep(1000);
+ }
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) { }
+
+ class EventDeviceManager implements Runnable {
+
+ private volatile boolean stop = false;
+
+ @Override
+ public void run() {
+ File f = new File("/dev/input/");
+ int number;
+ while(!stop){
+ for(String path:f.list()){
+ if(path.startsWith("event")) {
+ String stringNumber = path.substring(5);
+ number = Integer.parseInt(stringNumber);
+ if(number<32&&number>=0) {
+ if(eventDevicePollers[number]==null){
+ eventDevicePollers[number] = new EventDevicePoller(number);
+ Thread t = new Thread(eventDevicePollers[number], "NEWT-LinuxEventDeviceTracker-event"+number);
+ t.setDaemon(true);
+ t.start();
+ } else if(eventDevicePollers[number].stop) {
+ eventDevicePollers[number]=null;
+ }
+ }
+ }
+ }
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ class EventDevicePoller implements Runnable {
+
+ private volatile boolean stop = false;
+ private String eventDeviceName;
+
+ public EventDevicePoller(int eventDeviceNumber){
+ this.eventDeviceName="/dev/input/event"+eventDeviceNumber;
+ }
+
+ @Override
+ public void run() {
+ final byte[] b = new byte[16];
+ /**
+ * The Linux input event interface.
+ * http://www.kernel.org/doc/Documentation/input/input.txt
+ *
+ * struct input_event {
+ * struct timeval time;
+ * unsigned short type;
+ * unsigned short code;
+ * unsigned int value;
+ * };
+ */
+ ByteBuffer bb = ByteBuffer.wrap(b);
+ StructAccessor s = new StructAccessor(bb);
+ final File f = new File(eventDeviceName);
+ f.setReadOnly();
+ InputStream fis;
+ try {
+ fis = new FileInputStream(f);
+ } catch (FileNotFoundException e) {
+ stop=true;
+ return;
+ }
+
+ int timeSeconds;
+ int timeSecondFraction;
+ short type;
+ short code;
+ int value;
+
+ short keyCode=KeyEvent.VK_UNDEFINED;
+ char keyChar=' ';
+ short eventType=0;
+ int modifiers=0;
+
+ loop:
+ while(!stop) {
+ int remaining=16;
+ while(remaining>0) {
+ int read = 0;
+ try {
+ read = fis.read(b, 0, remaining);
+ } catch (IOException e) {
+ stop = true;
+ break loop;
+ }
+ if(read<0) {
+ stop = true; // EOF of event device file !?
+ break loop;
+ } else {
+ remaining -= read;
+ }
+ }
+
+ timeSeconds = s.getIntAt(0);
+ timeSecondFraction = s.getShortAt(4);
+ type = s.getShortAt(8);
+ code = s.getShortAt(10);
+ value = s.getIntAt(12);
+
+
+ /*
+ * Linux sends Keyboard events in the following order:
+ * EV_MSC (optional, contains scancode)
+ * EV_KEY
+ * SYN_REPORT (sent before next key)
+ */
+
+ switch(type) {
+ case 0: // SYN_REPORT
+ // Clear
+ eventType = 0;
+ keyCode = KeyEvent.VK_UNDEFINED;
+ keyChar = 0; // Print null for unprintable char.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[SYN_REPORT----]");
+ }
+ break;
+ case 1: // EV_KEY
+ keyCode = LinuxEVKey2NewtVKey(code); // The device independent code.
+ keyChar = NewtVKey2Unicode(keyCode, modifiers); // The printable character w/ key modifiers.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[EV_KEY: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+ }
+
+ switch(value) {
+ case 0:
+ eventType=KeyEvent.EVENT_KEY_RELEASED;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers &= ~InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers &= ~InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers &= ~InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers &= ~InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event released] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ break;
+ case 1:
+ eventType=KeyEvent.EVENT_KEY_PRESSED;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers |= InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers |= InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers |= InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event pressed] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ break;
+ case 2:
+ eventType=KeyEvent.EVENT_KEY_PRESSED;
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+
+ switch(keyCode) {
+ case KeyEvent.VK_SHIFT:
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ case KeyEvent.VK_ALT:
+ modifiers |= InputEvent.ALT_MASK;
+ break;
+ case KeyEvent.VK_ALT_GRAPH:
+ modifiers |= InputEvent.ALT_GRAPH_MASK;
+ break;
+ case KeyEvent.VK_CONTROL:
+ modifiers |= InputEvent.CTRL_MASK;
+ break;
+ }
+
+ if(null != focusedWindow) {
+ //Send syntetic autorepeat release
+ focusedWindow.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keyCode, keyChar);
+
+ focusedWindow.sendKeyEvent(eventType, modifiers, keyCode, keyCode, keyChar);
+ }
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("[event released auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ System.out.println("[event pressed auto] keyCode: "+keyCode+" keyChar: "+keyChar+ " modifiers: "+modifiers);
+ }
+ modifiers &= ~InputEvent.AUTOREPEAT_MASK;
+ break;
+ }
+ break;
+ case 4: // EV_MSC
+ if(code==4) { // MSC_SCAN
+ // scancode ignore, linux kernel specific
+ }
+ break;
+ // TODO: handle joystick events
+ // TODO: handle mouse events
+ // TODO: handle headphone/hdmi connector events
+ default: // Print number.
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("TODO EventDevicePoller: [time "+timeSeconds+":"+timeSecondFraction+"] type "+type+" / code "+code+" = value "+value);
+ }
+ }
+ }
+
+ if(null != fis) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ }
+ }
+ stop=true;
+ }
+
+ private char NewtVKey2Unicode(short VK, int modifiers) {
+ if( KeyEvent.isPrintableKey(VK, true) ) {
+ if((modifiers & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
+ return (char)VK;
+ } else {
+ return String.valueOf((char)VK).toLowerCase().charAt(0);
+ }
+ }
+ return 0;
+ }
+
+ @SuppressWarnings("unused")
+ private char LinuxEVKey2Unicode(short EVKey) {
+ // This is the stuff normally mapped by a system keymap
+
+ switch(EVKey) {
+ case 17: // w
+ return 'w';
+ case 31: // s
+ return 's';
+ case 30: // a
+ return 'a';
+ case 32: // d
+ return 'd';
+ case 1: // ESC
+ return 27;
+ case 28: // Enter
+ case 96: // Keypad Enter
+ return '\n';
+ case 57: // Space
+ return ' ';
+ case 11: // 0
+ case 82: // Numpad 0
+ return '0';
+ case 2: // 1
+ case 79: // Numpad 1
+ return '1';
+ case 3: // 2
+ case 80: // Numpad 1
+ return '2';
+ case 4: // 3
+ case 81: // Numpad 3
+ return '3';
+ case 5: // 4
+ case 75: // Numpad 4
+ return '4';
+ case 6: // 5
+ case 76: // Numpad 5
+ return '5';
+ case 7: // 6
+ case 77: // Numpad 6
+ return '6';
+ case 8: // 7
+ case 71: // Numpad 7
+ return '7';
+ case 9: // 8
+ case 72: // Numpad 8
+ return '8';
+ case 10: // 9
+ case 73: // Numpad 9
+ return '9';
+
+ default:
+ }
+
+ return 0;
+ }
+
+ private short LinuxEVKey2NewtVKey(short EVKey) {
+
+ switch(EVKey) {
+ case 1: // ESC
+ return KeyEvent.VK_ESCAPE;
+ case 2: // 1
+ return KeyEvent.VK_1;
+ case 79: // Numpad 1
+ return KeyEvent.VK_NUMPAD1;
+ case 3: // 2
+ return KeyEvent.VK_2;
+ case 80: // Numpad 2
+ return KeyEvent.VK_NUMPAD2;
+ case 4: // 3
+ return KeyEvent.VK_3;
+ case 81: // Numpad 3
+ return KeyEvent.VK_NUMPAD3;
+ case 5: // 4
+ return KeyEvent.VK_4;
+ case 75: // Numpad 4
+ return KeyEvent.VK_NUMPAD4;
+ case 6: // 5
+ return KeyEvent.VK_5;
+ case 76: // Numpad 5
+ return KeyEvent.VK_NUMPAD5;
+ case 7: // 6
+ return KeyEvent.VK_6;
+ case 77: // Numpad 6
+ return KeyEvent.VK_NUMPAD6;
+ case 8: // 7
+ return KeyEvent.VK_7;
+ case 71: // Numpad 7
+ return KeyEvent.VK_NUMPAD7;
+ case 9: // 8
+ return KeyEvent.VK_8;
+ case 72: // Numpad 8
+ return KeyEvent.VK_NUMPAD8;
+ case 10: // 9
+ return KeyEvent.VK_9;
+ case 73: // Numpad 9
+ return KeyEvent.VK_NUMPAD9;
+ case 11: // 0
+ return KeyEvent.VK_0;
+ case 82: // Numpad 0
+ return KeyEvent.VK_NUMPAD0;
+ case 12:
+ return KeyEvent.VK_MINUS;
+ case 13:
+ return KeyEvent.VK_EQUALS;
+ case 14: // Backspace
+ return KeyEvent.VK_BACK_SPACE;
+
+ case 15:
+ return KeyEvent.VK_TAB;
+ case 16:
+ return KeyEvent.VK_Q;
+ case 17: // w
+ return KeyEvent.VK_W;
+ case 18:
+ return KeyEvent.VK_E;
+ case 19:
+ return KeyEvent.VK_R;
+ case 20:
+ return KeyEvent.VK_T;
+ case 21:
+ return KeyEvent.VK_Y;
+ case 22:
+ return KeyEvent.VK_U;
+ case 23:
+ return KeyEvent.VK_I;
+ case 24:
+ return KeyEvent.VK_O;
+ case 25:
+ return KeyEvent.VK_P;
+ case 26: // left brace
+ return KeyEvent.VK_LEFT_PARENTHESIS;
+ case 27: // right brace
+ return KeyEvent.VK_RIGHT_PARENTHESIS;
+ case 28: // Enter
+ case 96: // Keypad Enter
+ return KeyEvent.VK_ENTER;
+
+ case 29: // left ctrl
+ return KeyEvent.VK_CONTROL;
+ case 30: // a
+ return KeyEvent.VK_A;
+ case 31: // s
+ return KeyEvent.VK_S;
+ case 32: // d
+ return KeyEvent.VK_D;
+ case 33:
+ return KeyEvent.VK_F;
+ case 34:
+ return KeyEvent.VK_G;
+ case 35:
+ return KeyEvent.VK_H;
+ case 36:
+ return KeyEvent.VK_J;
+ case 37:
+ return KeyEvent.VK_K;
+ case 38:
+ return KeyEvent.VK_L;
+ case 39:
+ return KeyEvent.VK_SEMICOLON;
+ case 40: // apostrophe
+ return KeyEvent.VK_QUOTE;
+ case 41: // grave
+ return KeyEvent.VK_BACK_QUOTE;
+
+ case 42: // left shift
+ return KeyEvent.VK_SHIFT;
+ case 43:
+ return KeyEvent.VK_BACK_SLASH;
+ case 44:
+ return KeyEvent.VK_Z;
+ case 45:
+ return KeyEvent.VK_X;
+ case 46:
+ return KeyEvent.VK_C;
+ case 47:
+ return KeyEvent.VK_V;
+ case 48:
+ return KeyEvent.VK_B;
+ case 49:
+ return KeyEvent.VK_N;
+ case 50:
+ return KeyEvent.VK_M;
+ case 51:
+ return KeyEvent.VK_COMMA;
+ case 52: // dot
+ return KeyEvent.VK_PERIOD;
+ case 53:
+ return KeyEvent.VK_SLASH;
+ case 54:
+ return KeyEvent.VK_SHIFT;
+ case 55: // kp asterisk
+ return KeyEvent.VK_ASTERISK;
+ case 56: // left alt
+ return KeyEvent.VK_ALT;
+ case 57: // Space
+ return KeyEvent.VK_SPACE;
+ case 58:
+ return KeyEvent.VK_CAPS_LOCK;
+
+ case 59:
+ return KeyEvent.VK_F1;
+ case 60:
+ return KeyEvent.VK_F2;
+ case 61:
+ return KeyEvent.VK_F3;
+ case 62:
+ return KeyEvent.VK_F4;
+ case 63:
+ return KeyEvent.VK_F5;
+ case 64:
+ return KeyEvent.VK_F6;
+ case 65:
+ return KeyEvent.VK_F7;
+ case 66:
+ return KeyEvent.VK_F8;
+ case 67:
+ return KeyEvent.VK_F9;
+ case 68:
+ return KeyEvent.VK_F10;
+
+ case 69:
+ return KeyEvent.VK_NUM_LOCK;
+ case 70:
+ return KeyEvent.VK_SCROLL_LOCK;
+
+ case 74: // kp minus
+ return KeyEvent.VK_MINUS;
+ case 78: // kp plus
+ return KeyEvent.VK_PLUS;
+ case 83: // kp dot
+ return KeyEvent.VK_PERIOD;
+
+ // TODO: add mappings for japanese special buttons
+ case 85: // zenkakuhankaku
+ case 86: // 102nd
+ break; // FIXME
+
+ case 87:
+ return KeyEvent.VK_F11;
+ case 88:
+ return KeyEvent.VK_F12;
+
+ case 89: // ro
+ return KeyEvent.VK_ROMAN_CHARACTERS;
+ case 90: // Katakana
+ return KeyEvent.VK_KATAKANA;
+ case 91:
+ return KeyEvent.VK_HIRAGANA;
+
+ case 92: // kenkan
+ break; // FIXME
+ case 93: // katakana hiragana
+ break; // FIXME
+ case 94: // mu henkan
+ break; // FIXME
+ case 95: // kp jp comma
+ break; // FIXME
+
+ case 97: // right ctrl
+ return KeyEvent.VK_CONTROL;
+ case 98: // kp slash
+ return KeyEvent.VK_SLASH;
+
+ case 99: // sysrq
+ break; // FIXME
+
+ case 100: // right alt
+ return KeyEvent.VK_ALT;
+ case 101: // linefeed
+ break; // FIXME
+ case 102: // home
+ return KeyEvent.VK_HOME;
+ case 103: // KEY_UP
+ return KeyEvent.VK_UP;
+ case 104:
+ return KeyEvent.VK_PAGE_UP;
+ case 105: // KEY_LEFT
+ return KeyEvent.VK_LEFT;
+ case 106: // KEY_RIGHT
+ return KeyEvent.VK_RIGHT;
+ case 107:
+ return KeyEvent.VK_END;
+ case 108: // KEY_DOWN
+ return KeyEvent.VK_DOWN;
+ case 109:
+ return KeyEvent.VK_PAGE_DOWN;
+ case 110:
+ return KeyEvent.VK_INSERT;
+ case 111: // del
+ return KeyEvent.VK_DELETE;
+
+ case 112: // macro
+ break; // FIXME DEAD_MACRON?
+ case 113: // mute
+ break; // FIXME
+ case 114: // vol up
+ break; // FIXME
+ case 115: // vol down
+ break; // FIXME
+ case 116: // power
+ break; // FIXME
+
+ case 117: // kp equals
+ return KeyEvent.VK_EQUALS;
+ case 118: // kp plus minux
+ break; // FIXME
+ case 119: // pause
+ return KeyEvent.VK_PAUSE;
+ case 120: // scale AL compiz scale expose
+ break; // FIXME
+ case 121: // kp comma
+ return KeyEvent.VK_COMMA;
+ case 122: // hangeul
+ break; // FIXME
+ case 123: // hanja
+ break; // FIXME
+ case 124: // yen
+ break; // FIXME
+
+ case 125: // left meta
+ case 126: // right meta
+ return KeyEvent.VK_META;
+ case 127: // compose
+ return KeyEvent.VK_COMPOSE;
+
+ case 128: // stop
+ return KeyEvent.VK_STOP;
+ case 129: // again
+ return KeyEvent.VK_AGAIN;
+ case 130: // properties
+ return KeyEvent.VK_PROPS;
+ case 131: // undo
+ return KeyEvent.VK_UNDO;
+ case 132: // front
+ break; // FIXME
+ case 133: // copy
+ return KeyEvent.VK_COPY;
+ case 134: // open
+ break; // FIXME
+ case 135: // paste
+ return KeyEvent.VK_PASTE;
+ case 136: // find
+ return KeyEvent.VK_FIND;
+ case 137: // cut
+ return KeyEvent.VK_CUT;
+ case 138: // help
+ return KeyEvent.VK_HELP;
+ case 139: // menu
+ break; // FIXME
+ case 140: // calc
+ break; // FIXME
+ case 141: // setup
+ break; // FIXME
+ case 142: // sleep
+ break; // FIXME
+ case 143: // wakeup
+ break; // FIXME
+ case 144: // file
+ break; // FIXME
+ case 145: // send file
+ break; // FIXME
+ case 146: // delete file
+ break; // FIXME
+ case 147: // xfer
+ break; // FIXME
+ case 148: // prog1
+ break; // FIXME
+ case 149: // prog2
+ break; // FIXME
+ case 150: // www
+ break; // FIXME
+ case 151: // msdos
+ break; // FIXME
+ case 152: // coffee
+ break; // FIXME
+ case 153: // direction
+ break; // FIXME
+ case 154: // cycle windows
+ break; // FIXME
+ case 155: // mail
+ break; // FIXME
+ case 156: // bookmarks
+ break; // FIXME
+ case 157: // computer
+ break; // FIXME
+ case 158: // back
+ break; // FIXME
+ case 159: // forward
+ break; // FIXME
+ case 160: // close cd
+ break; // FIXME
+ case 161: // eject cd
+ break; // FIXME
+ case 162: // eject close cd
+ break; // FIXME
+ case 163: // next song
+ break; // FIXME
+ case 164: // play pause
+ break; // FIXME
+ case 165: // previous song
+ break; // FIXME
+ case 166: // stop cd
+ break; // FIXME
+ case 167: // record
+ break; // FIXME
+ case 168: // rewind
+ break; // FIXME
+ case 169: // phone
+ break; // FIXME
+ case 170: // ISO
+ break; // FIXME
+ case 171: // config
+ break; // FIXME
+ case 172: // home page
+ break; // FIXME
+ case 173: // refresh
+ break; // FIXME
+ case 174: // exit
+ break; // FIXME
+ case 175: // move
+ break; // FIXME
+ case 176: // edit
+ break; // FIXME
+ case 177: // scroll up
+ break; // FIXME PAGE_UP?
+ case 178: // scroll down
+ break; // FIXME PAGE_DOWN?
+ case 179: // kp left paren
+ return KeyEvent.VK_LEFT_PARENTHESIS;
+ case 180: // kp right paren
+ return KeyEvent.VK_RIGHT_PARENTHESIS;
+ case 181: // new
+ break; // FIXME
+ case 182: // redo
+ break; // FIXME
+
+ case 183: // F13
+ return KeyEvent.VK_F13;
+ case 184: // F14
+ return KeyEvent.VK_F14;
+ case 185: // F15
+ return KeyEvent.VK_F15;
+ case 186: // F16
+ return KeyEvent.VK_F16;
+ case 187: // F17
+ return KeyEvent.VK_F17;
+ case 188: // F18
+ return KeyEvent.VK_F18;
+ case 189: // F19
+ return KeyEvent.VK_F19;
+ case 190: // F20
+ return KeyEvent.VK_F20;
+ case 191: // F21
+ return KeyEvent.VK_F21;
+ case 192: // F22
+ return KeyEvent.VK_F22;
+ case 193: // F23
+ return KeyEvent.VK_F23;
+ case 194: // F24
+ return KeyEvent.VK_F24;
+
+ case 200: // play cd
+ break; // FIXME
+ case 201: // pause cd
+ break; // FIXME
+ case 202: // prog 3
+ break; // FIXME
+ case 203: // prog 4
+ break; // FIXME
+ case 204: // dashboard
+ break; // FIXME
+ case 205: // suspend
+ break; // FIXME
+ case 206: // close
+ break; // FIXME
+ case 207: // play
+ break; // FIXME
+ case 208: // fast forward
+ break; // FIXME
+ case 210: // print
+ return KeyEvent.VK_PRINTSCREEN; // FIXME ?
+ case 211: // HP
+ break; // FIXME
+ case 212: // camera
+ break; // FIXME
+ case 213: // sound
+ break; // FIXME
+ case 214: // question
+ break; // FIXME
+ case 215: // email
+ break; // FIXME
+ case 216: // chat
+ break; // FIXME
+ case 217: // search
+ break; // FIXME
+ case 218: // connect
+ break; // FIXME
+ case 219: // finance
+ break; // FIXME
+ case 220: // sport
+ break; // FIXME
+ case 221: // shop
+ break; // FIXME
+ case 222: // alt erase
+ break; // FIXME
+ case 223: // cancel
+ break; // FIXME
+ case 224: // brightness down
+ break; // FIXME
+ case 225: // brightness up
+ break; // FIXME
+ case 226: // media
+ break; // FIXME
+ case 227: // switch video mode
+ break; // FIXME
+ case 228: // kb dillum toggle
+ break; // FIXME
+ case 229: // kb dillum down
+ break; // FIXME
+ case 230: // kb dillum up
+ break; // FIXME
+ case 231: // send
+ break; // FIXME
+ case 232: // reply
+ break; // FIXME
+ case 233: // forward mail
+ break; // FIXME
+ case 234: // save
+ break; // FIXME
+ case 235: // documents
+ break; // FIXME
+ case 236: // battery
+ break; // FIXME
+ case 237: // bluetooth
+ break; // FIXME
+ case 238: // wlan
+ break; // FIXME
+ case 239: // UWB
+ break; // FIXME
+ case 240: // unknown
+ return KeyEvent.VK_UNDEFINED;
+ case 241: // video next
+ break; // FIXME
+ case 242: // video prev
+ break; // FIXME
+ case 243: // brightness cycle
+ break; // FIXME
+ case 244: // brightness zero
+ break; // FIXME
+ case 245: // display off
+ break; // FIXME
+ case 246: // wimax
+ break; // FIXME
+ case 247: // rf kill radio off
+ break; // FIXME
+ case 248: // mic mute
+ break; // FIXME
+
+ default:
+ }
+
+ if(Window.DEBUG_KEY_EVENT) {
+ System.out.println("TODO LinuxEVKey2NewtVKey: Unmapped EVKey "+EVKey);
+ }
+
+ return KeyEvent.VK_UNDEFINED;
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
new file mode 100644
index 000000000..9d7b8931b
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/linux/LinuxMouseTracker.java
@@ -0,0 +1,224 @@
+/**
+ * Copyright 2012 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.linux;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import jogamp.newt.WindowImpl;
+
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+
+/**
+ * Experimental native mouse tracker thread for GNU/Linux
+ * just reading <code>/dev/input/mice</code>
+ * within it's own polling thread.
+ */
+public class LinuxMouseTracker implements WindowListener {
+
+ private static final LinuxMouseTracker lmt;
+
+ static {
+ lmt = new LinuxMouseTracker();
+ final Thread t = new Thread(lmt.mouseDevicePoller, "NEWT-LinuxMouseTracker");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public static LinuxMouseTracker getSingleton() {
+ return lmt;
+ }
+
+ private volatile boolean stop = false;
+ private int x = 0;
+ private int y = 0;
+ private short buttonDown = 0;
+ private int old_x = 0;
+ private int old_y = 0;
+ private volatile int lastFocusedX = 0;
+ private volatile int lastFocusedY = 0;
+ private short old_buttonDown = 0;
+ private WindowImpl focusedWindow = null;
+ private final MouseDevicePoller mouseDevicePoller = new MouseDevicePoller();
+
+ public final int getLastX() { return lastFocusedX; }
+ public final int getLastY() { return lastFocusedY; }
+
+ @Override
+ public void windowResized(WindowEvent e) { }
+
+ @Override
+ public void windowMoved(WindowEvent e) { }
+
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ @Override
+ public void windowDestroyed(WindowEvent e) { }
+
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ Object s = e.getSource();
+ if(s instanceof WindowImpl) {
+ focusedWindow = (WindowImpl) s;
+ }
+ }
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ Object s = e.getSource();
+ if(focusedWindow == s) {
+ focusedWindow = null;
+ }
+ }
+
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) { }
+
+ class MouseDevicePoller implements Runnable {
+ @Override
+ public void run() {
+ final byte[] b = new byte[3];
+ final File f = new File("/dev/input/mice");
+ f.setReadOnly();
+ InputStream fis;
+ try {
+ fis = new FileInputStream(f);
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return;
+ }
+ int xd=0,yd=0; //x/y movement delta
+ boolean xo=false,yo=false; // x/y overflow (out of range -255 to +255)
+ boolean lb=false,mb=false,rb=false,hs=false,vs=false; //left/middle/right mousebutton
+ while(!stop) {
+ int remaining=3;
+ while(remaining>0) {
+ int read = 0;
+ try {
+ read = fis.read(b, 0, remaining);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if(read<0) {
+ stop = true; // EOF of mouse !?
+ } else {
+ remaining -= read;
+ }
+ }
+ lb=(b[0]&1)>0;
+ rb=(b[0]&2)>0;
+ mb=(b[0]&4)>0;
+ hs=(b[0]&16)>0;
+ vs=(b[0]&32)>0;
+ xo=(b[0]&64)>0;
+ yo=(b[0]&128)>0;
+ xd=b[1];
+ yd=b[2];
+
+ x+=xd;
+ y-=yd;
+
+ if(x<0) {
+ x=0;
+ }
+ if(y<0) {
+ y=0;
+ }
+
+ buttonDown = 0;
+ if(lb) {
+ buttonDown = MouseEvent.BUTTON1;
+ }
+ if(mb) {
+ buttonDown = MouseEvent.BUTTON2;
+ }
+ if(rb) {
+ buttonDown = MouseEvent.BUTTON3;
+ }
+
+ if(null != focusedWindow) {
+ if( x >= focusedWindow.getScreen().getWidth() ) {
+ x = focusedWindow.getScreen().getWidth() - 1;
+ }
+ if( y >= focusedWindow.getScreen().getHeight() ) {
+ y = focusedWindow.getScreen().getHeight() - 1;
+ }
+ final int wx = x - focusedWindow.getX(), wy = y - focusedWindow.getY();
+ if(old_x != x || old_y != y) {
+ // mouse moved
+ lastFocusedX = wx;
+ lastFocusedY = wy;
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_MOVED, 0, wx, wy, (short)0, 0 );
+ }
+
+ if(old_buttonDown != buttonDown) {
+ // press/release
+ if( 0 != buttonDown ) {
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_PRESSED, 0, wx, wy, buttonDown, 0 );
+ } else {
+ focusedWindow.sendMouseEvent(MouseEvent.EVENT_MOUSE_RELEASED, 0, wx, wy, old_buttonDown, 0 );
+ }
+ }
+ } else {
+ if(Window.DEBUG_MOUSE_EVENT) {
+ System.out.println(x+"/"+y+", hs="+hs+",vs="+vs+",lb="+lb+",rb="+rb+",mb="+mb+",xo="+xo+",yo="+yo+"xd="+xd+",yd="+yd);
+ }
+ }
+
+ old_x = x;
+ old_y = y;
+ old_buttonDown = buttonDown;
+
+ }
+ if(null != fis) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index 18f8d9538..d850a18af 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -1,21 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * Copyright (c) 2012 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -28,29 +29,61 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.macosx;
+import java.net.URLConnection;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-public class MacDisplay extends DisplayImpl {
+public class DisplayDriver extends DisplayImpl {
+ private static final PNGPixelRect defaultIconData;
+
static {
NEWTJNILibLoader.loadNEWT();
if(!initNSApplication0()) {
throw new NativeWindowException("Failed to initialize native Application hook");
}
- if(!MacWindow.initIDs0()) {
+ if(!WindowDriver.initIDs0()) {
throw new NativeWindowException("Failed to initialize jmethodIDs");
}
+ {
+ PNGPixelRect image=null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ try {
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconData = image;
+ if( null != defaultIconData ) {
+ final Buffer pixels = defaultIconData.getPixels();
+ DisplayDriver.setAppIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ defaultIconData.getSize().getWidth(), defaultIconData.getSize().getHeight());
+ }
+ }
+
if(DEBUG) {
System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName());
}
@@ -59,19 +92,45 @@ public class MacDisplay extends DisplayImpl {
public static void initSingleton() {
// just exist to ensure static init has been run
}
-
- public MacDisplay() {
+
+ public DisplayDriver() {
}
+ @Override
protected void dispatchMessagesNative() {
// nop
}
-
+
+ @Override
protected void createNativeImpl() {
aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() { }
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
+ @Override
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) {
+ destroyPointerIcon0(piHandle);
+ }
public static void runNSApplication() {
runNSApplication0();
@@ -83,5 +142,9 @@ public class MacDisplay extends DisplayImpl {
private static native boolean initNSApplication0();
private static native void runNSApplication0();
private static native void stopNSApplication0();
+ /* pp */ static native void setAppIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height);
+ private static native long createPointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+ private static native long destroyPointerIcon0(long handle);
+
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
index 46625f7a9..a89150d7c 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java
@@ -1,59 +1,159 @@
+/**
+ * Copyright 2011 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.macosx;
import com.jogamp.newt.event.KeyEvent;
public class MacKeyUtil {
-
- // KeyCodes (independent)
- private static final int kVK_Return = 0x24;
- private static final int kVK_Tab = 0x30;
- private static final int kVK_Space = 0x31;
- private static final int kVK_Delete = 0x33;
- private static final int kVK_Escape = 0x35;
- private static final int kVK_Command = 0x37;
- private static final int kVK_Shift = 0x38;
- private static final int kVK_CapsLock = 0x39;
- private static final int kVK_Option = 0x3A;
- private static final int kVK_Control = 0x3B;
- private static final int kVK_RightShift = 0x3C;
- private static final int kVK_RightOption = 0x3D;
- private static final int kVK_RightControl = 0x3E;
- private static final int kVK_Function = 0x3F;
- private static final int kVK_F17 = 0x40;
- private static final int kVK_VolumeUp = 0x48;
- private static final int kVK_VolumeDown = 0x49;
- private static final int kVK_Mute = 0x4A;
- private static final int kVK_F18 = 0x4F;
- private static final int kVK_F19 = 0x50;
- private static final int kVK_F20 = 0x5A;
- private static final int kVK_F5 = 0x60;
- private static final int kVK_F6 = 0x61;
- private static final int kVK_F7 = 0x62;
- private static final int kVK_F3 = 0x63;
- private static final int kVK_F8 = 0x64;
- private static final int kVK_F9 = 0x65;
- private static final int kVK_F11 = 0x67;
- private static final int kVK_F13 = 0x69;
- private static final int kVK_F16 = 0x6A;
- private static final int kVK_F14 = 0x6B;
- private static final int kVK_F10 = 0x6D;
- private static final int kVK_F12 = 0x6F;
- private static final int kVK_F15 = 0x71;
- private static final int kVK_Help = 0x72;
- private static final int kVK_Home = 0x73;
- private static final int kVK_PageUp = 0x74;
- private static final int kVK_ForwardDelete = 0x75;
- private static final int kVK_F4 = 0x76;
- private static final int kVK_End = 0x77;
- private static final int kVK_F2 = 0x78;
- private static final int kVK_PageDown = 0x79;
- private static final int kVK_F1 = 0x7A;
- private static final int kVK_LeftArrow = 0x7B;
- private static final int kVK_RightArrow = 0x7C;
- private static final int kVK_DownArrow = 0x7D;
- private static final int kVK_UpArrow = 0x7E;
-
+
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ private static final short kVK_ANSI_A = 0x00;
+ private static final short kVK_ANSI_S = 0x01;
+ private static final short kVK_ANSI_D = 0x02;
+ private static final short kVK_ANSI_F = 0x03;
+ private static final short kVK_ANSI_H = 0x04;
+ private static final short kVK_ANSI_G = 0x05;
+ private static final short kVK_ANSI_Z = 0x06;
+ private static final short kVK_ANSI_X = 0x07;
+ private static final short kVK_ANSI_C = 0x08;
+ private static final short kVK_ANSI_V = 0x09;
+ private static final short kVK_ANSI_B = 0x0B;
+ private static final short kVK_ANSI_Q = 0x0C;
+ private static final short kVK_ANSI_W = 0x0D;
+ private static final short kVK_ANSI_E = 0x0E;
+ private static final short kVK_ANSI_R = 0x0F;
+ private static final short kVK_ANSI_Y = 0x10;
+ private static final short kVK_ANSI_T = 0x11;
+ private static final short kVK_ANSI_1 = 0x12;
+ private static final short kVK_ANSI_2 = 0x13;
+ private static final short kVK_ANSI_3 = 0x14;
+ private static final short kVK_ANSI_4 = 0x15;
+ private static final short kVK_ANSI_6 = 0x16;
+ private static final short kVK_ANSI_5 = 0x17;
+ private static final short kVK_ANSI_Equal = 0x18;
+ private static final short kVK_ANSI_9 = 0x19;
+ private static final short kVK_ANSI_7 = 0x1A;
+ private static final short kVK_ANSI_Minus = 0x1B;
+ private static final short kVK_ANSI_8 = 0x1C;
+ private static final short kVK_ANSI_0 = 0x1D;
+ private static final short kVK_ANSI_RightBracket = 0x1E;
+ private static final short kVK_ANSI_O = 0x1F;
+ private static final short kVK_ANSI_U = 0x20;
+ private static final short kVK_ANSI_LeftBracket = 0x21;
+ private static final short kVK_ANSI_I = 0x22;
+ private static final short kVK_ANSI_P = 0x23;
+ private static final short kVK_ANSI_L = 0x25;
+ private static final short kVK_ANSI_J = 0x26;
+ private static final short kVK_ANSI_Quote = 0x27;
+ private static final short kVK_ANSI_K = 0x28;
+ private static final short kVK_ANSI_Semicolon = 0x29;
+ private static final short kVK_ANSI_Backslash = 0x2A;
+ private static final short kVK_ANSI_Comma = 0x2B;
+ private static final short kVK_ANSI_Slash = 0x2C;
+ private static final short kVK_ANSI_N = 0x2D;
+ private static final short kVK_ANSI_M = 0x2E;
+ private static final short kVK_ANSI_Period = 0x2F;
+ private static final short kVK_ANSI_Grave = 0x32;
+ private static final short kVK_ANSI_KeypadDecimal = 0x41;
+ private static final short kVK_ANSI_KeypadMultiply = 0x43;
+ private static final short kVK_ANSI_KeypadPlus = 0x45;
+ private static final short kVK_ANSI_KeypadClear = 0x47;
+ private static final short kVK_ANSI_KeypadDivide = 0x4B;
+ private static final short kVK_ANSI_KeypadEnter = 0x4C;
+ private static final short kVK_ANSI_KeypadMinus = 0x4E;
+ private static final short kVK_ANSI_KeypadEquals = 0x51;
+ private static final short kVK_ANSI_Keypad0 = 0x52;
+ private static final short kVK_ANSI_Keypad1 = 0x53;
+ private static final short kVK_ANSI_Keypad2 = 0x54;
+ private static final short kVK_ANSI_Keypad3 = 0x55;
+ private static final short kVK_ANSI_Keypad4 = 0x56;
+ private static final short kVK_ANSI_Keypad5 = 0x57;
+ private static final short kVK_ANSI_Keypad6 = 0x58;
+ private static final short kVK_ANSI_Keypad7 = 0x59;
+ private static final short kVK_ANSI_Keypad8 = 0x5B;
+ private static final short kVK_ANSI_Keypad9 = 0x5C;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ private static final short kVK_Return = 0x24;
+ private static final short kVK_Tab = 0x30;
+ private static final short kVK_Space = 0x31;
+ private static final short kVK_Delete = 0x33;
+ private static final short kVK_Escape = 0x35;
+ private static final short kVK_Command = 0x37;
+ private static final short kVK_Shift = 0x38;
+ private static final short kVK_CapsLock = 0x39;
+ private static final short kVK_Option = 0x3A;
+ private static final short kVK_Control = 0x3B;
+ private static final short kVK_RightShift = 0x3C;
+ private static final short kVK_RightOption = 0x3D;
+ private static final short kVK_RightControl = 0x3E;
+ // private static final short kVK_Function = 0x3F;
+ private static final short kVK_F17 = 0x40;
+ // private static final short kVK_VolumeUp = 0x48;
+ // private static final short kVK_VolumeDown = 0x49;
+ // private static final short kVK_Mute = 0x4A;
+ private static final short kVK_F18 = 0x4F;
+ private static final short kVK_F19 = 0x50;
+ private static final short kVK_F20 = 0x5A;
+ private static final short kVK_F5 = 0x60;
+ private static final short kVK_F6 = 0x61;
+ private static final short kVK_F7 = 0x62;
+ private static final short kVK_F3 = 0x63;
+ private static final short kVK_F8 = 0x64;
+ private static final short kVK_F9 = 0x65;
+ private static final short kVK_F11 = 0x67;
+ private static final short kVK_F13 = 0x69;
+ private static final short kVK_F16 = 0x6A;
+ private static final short kVK_F14 = 0x6B;
+ private static final short kVK_F10 = 0x6D;
+ private static final short kVK_F12 = 0x6F;
+ private static final short kVK_F15 = 0x71;
+ private static final short kVK_Help = 0x72;
+ private static final short kVK_Home = 0x73;
+ private static final short kVK_PageUp = 0x74;
+ private static final short kVK_ForwardDelete = 0x75;
+ private static final short kVK_F4 = 0x76;
+ private static final short kVK_End = 0x77;
+ private static final short kVK_F2 = 0x78;
+ private static final short kVK_PageDown = 0x79;
+ private static final short kVK_F1 = 0x7A;
+ private static final short kVK_LeftArrow = 0x7B;
+ private static final short kVK_RightArrow = 0x7C;
+ private static final short kVK_DownArrow = 0x7D;
+ private static final short kVK_UpArrow = 0x7E;
+
+ //
// Key constants handled differently on Mac OS X than other platforms
+ //
private static final char NSUpArrowFunctionKey = 0xF700;
private static final char NSDownArrowFunctionKey = 0xF701;
private static final char NSLeftArrowFunctionKey = 0xF702;
@@ -82,6 +182,7 @@ public class MacKeyUtil {
private static final char NSF22FunctionKey = 0xF719;
private static final char NSF23FunctionKey = 0xF71A;
private static final char NSF24FunctionKey = 0xF71B;
+ /**
private static final char NSF25FunctionKey = 0xF71C;
private static final char NSF26FunctionKey = 0xF71D;
private static final char NSF27FunctionKey = 0xF71E;
@@ -93,6 +194,7 @@ public class MacKeyUtil {
private static final char NSF33FunctionKey = 0xF724;
private static final char NSF34FunctionKey = 0xF725;
private static final char NSF35FunctionKey = 0xF726;
+ */
private static final char NSInsertFunctionKey = 0xF727;
private static final char NSDeleteFunctionKey = 0xF728;
private static final char NSHomeFunctionKey = 0xF729;
@@ -103,10 +205,11 @@ public class MacKeyUtil {
private static final char NSPrintScreenFunctionKey = 0xF72E;
private static final char NSScrollLockFunctionKey = 0xF72F;
private static final char NSPauseFunctionKey = 0xF730;
- private static final char NSSysReqFunctionKey = 0xF731;
- private static final char NSBreakFunctionKey = 0xF732;
- private static final char NSResetFunctionKey = 0xF733;
+ // private static final char NSSysReqFunctionKey = 0xF731;
+ // private static final char NSBreakFunctionKey = 0xF732;
+ // private static final char NSResetFunctionKey = 0xF733;
private static final char NSStopFunctionKey = 0xF734;
+ /**
private static final char NSMenuFunctionKey = 0xF735;
private static final char NSUserFunctionKey = 0xF736;
private static final char NSSystemFunctionKey = 0xF737;
@@ -126,26 +229,99 @@ public class MacKeyUtil {
private static final char NSFindFunctionKey = 0xF745;
private static final char NSHelpFunctionKey = 0xF746;
private static final char NSModeSwitchFunctionKey = 0xF747;
-
- static int validateKeyCode(int keyCode, char keyChar) {
+ */
+
+ static short validateKeyCode(short keyCode, char keyChar) {
// OS X Virtual Keycodes
switch(keyCode) {
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ case kVK_ANSI_A: return KeyEvent.VK_A;
+ case kVK_ANSI_S: return KeyEvent.VK_S;
+ case kVK_ANSI_D: return KeyEvent.VK_D;
+ case kVK_ANSI_F: return KeyEvent.VK_F;
+ case kVK_ANSI_H: return KeyEvent.VK_H;
+ case kVK_ANSI_G: return KeyEvent.VK_G;
+ case kVK_ANSI_Z: return KeyEvent.VK_Z;
+ case kVK_ANSI_X: return KeyEvent.VK_X;
+ case kVK_ANSI_C: return KeyEvent.VK_C;
+ case kVK_ANSI_V: return KeyEvent.VK_V;
+ case kVK_ANSI_B: return KeyEvent.VK_B;
+ case kVK_ANSI_Q: return KeyEvent.VK_Q;
+ case kVK_ANSI_W: return KeyEvent.VK_W;
+ case kVK_ANSI_E: return KeyEvent.VK_E;
+ case kVK_ANSI_R: return KeyEvent.VK_R;
+ case kVK_ANSI_Y: return KeyEvent.VK_Y;
+ case kVK_ANSI_T: return KeyEvent.VK_T;
+ case kVK_ANSI_1: return KeyEvent.VK_1;
+ case kVK_ANSI_2: return KeyEvent.VK_2;
+ case kVK_ANSI_3: return KeyEvent.VK_3;
+ case kVK_ANSI_4: return KeyEvent.VK_4;
+ case kVK_ANSI_6: return KeyEvent.VK_6;
+ case kVK_ANSI_5: return KeyEvent.VK_5;
+ case kVK_ANSI_Equal: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_9: return KeyEvent.VK_9;
+ case kVK_ANSI_7: return KeyEvent.VK_7;
+ case kVK_ANSI_Minus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_8: return KeyEvent.VK_8;
+ case kVK_ANSI_0: return KeyEvent.VK_0;
+ case kVK_ANSI_RightBracket: return KeyEvent.VK_CLOSE_BRACKET;
+ case kVK_ANSI_O: return KeyEvent.VK_O;
+ case kVK_ANSI_U: return KeyEvent.VK_U;
+ case kVK_ANSI_LeftBracket: return KeyEvent.VK_OPEN_BRACKET;
+ case kVK_ANSI_I: return KeyEvent.VK_I;
+ case kVK_ANSI_P: return KeyEvent.VK_P;
+ case kVK_ANSI_L: return KeyEvent.VK_L;
+ case kVK_ANSI_J: return KeyEvent.VK_J;
+ case kVK_ANSI_Quote: return KeyEvent.VK_QUOTE;
+ case kVK_ANSI_K: return KeyEvent.VK_K;
+ case kVK_ANSI_Semicolon: return KeyEvent.VK_SEMICOLON;
+ case kVK_ANSI_Backslash: return KeyEvent.VK_BACK_SLASH;
+ case kVK_ANSI_Comma: return KeyEvent.VK_COMMA;
+ case kVK_ANSI_Slash: return KeyEvent.VK_SLASH;
+ case kVK_ANSI_N: return KeyEvent.VK_N;
+ case kVK_ANSI_M: return KeyEvent.VK_M;
+ case kVK_ANSI_Period: return KeyEvent.VK_PERIOD;
+ case kVK_ANSI_Grave: return KeyEvent.VK_BACK_QUOTE; // KeyEvent.VK_DEAD_GRAVE
+ case kVK_ANSI_KeypadDecimal: return KeyEvent.VK_DECIMAL;
+ case kVK_ANSI_KeypadMultiply: return KeyEvent.VK_MULTIPLY;
+ case kVK_ANSI_KeypadPlus: return KeyEvent.VK_PLUS;
+ case kVK_ANSI_KeypadClear: return KeyEvent.VK_CLEAR;
+ case kVK_ANSI_KeypadDivide: return KeyEvent.VK_DIVIDE;
+ case kVK_ANSI_KeypadEnter: return KeyEvent.VK_ENTER;
+ case kVK_ANSI_KeypadMinus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_KeypadEquals: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_Keypad0: return KeyEvent.VK_0;
+ case kVK_ANSI_Keypad1: return KeyEvent.VK_1;
+ case kVK_ANSI_Keypad2: return KeyEvent.VK_2;
+ case kVK_ANSI_Keypad3: return KeyEvent.VK_3;
+ case kVK_ANSI_Keypad4: return KeyEvent.VK_4;
+ case kVK_ANSI_Keypad5: return KeyEvent.VK_5;
+ case kVK_ANSI_Keypad6: return KeyEvent.VK_6;
+ case kVK_ANSI_Keypad7: return KeyEvent.VK_7;
+ case kVK_ANSI_Keypad8: return KeyEvent.VK_8;
+ case kVK_ANSI_Keypad9: return KeyEvent.VK_9;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
case kVK_Return: return KeyEvent.VK_ENTER;
case kVK_Tab: return KeyEvent.VK_TAB;
case kVK_Space: return KeyEvent.VK_SPACE;
case kVK_Delete: return KeyEvent.VK_BACK_SPACE;
case kVK_Escape: return KeyEvent.VK_ESCAPE;
- case kVK_Command: return KeyEvent.VK_ALT;
+ case kVK_Command: return KeyEvent.VK_WINDOWS;
case kVK_Shift: return KeyEvent.VK_SHIFT;
case kVK_CapsLock: return KeyEvent.VK_CAPS_LOCK;
- case kVK_Option: return KeyEvent.VK_WINDOWS;
+ case kVK_Option: return KeyEvent.VK_ALT;
case kVK_Control: return KeyEvent.VK_CONTROL;
case kVK_RightShift: return KeyEvent.VK_SHIFT;
- case kVK_RightOption: return KeyEvent.VK_WINDOWS;
+ case kVK_RightOption: return KeyEvent.VK_ALT_GRAPH;
case kVK_RightControl: return KeyEvent.VK_CONTROL;
// case kVK_Function: return KeyEvent.VK_F;
case kVK_F17: return KeyEvent.VK_F17;
- // case kVK_VolumeUp:
+ // case kVK_VolumeUp:
// case kVK_VolumeDown:
// case kVK_Mute:
case kVK_F18: return KeyEvent.VK_F18;
@@ -178,85 +354,73 @@ public class MacKeyUtil {
case kVK_DownArrow: return KeyEvent.VK_DOWN;
case kVK_UpArrow: return KeyEvent.VK_UP;
}
-
- if (keyChar == '\r') {
- // Turn these into \n
- return KeyEvent.VK_ENTER;
- }
-
- if (keyChar >= NSUpArrowFunctionKey && keyChar <= NSModeSwitchFunctionKey) {
- switch (keyChar) {
- case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
- case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
- case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
- case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
- case NSF1FunctionKey: return KeyEvent.VK_F1;
- case NSF2FunctionKey: return KeyEvent.VK_F2;
- case NSF3FunctionKey: return KeyEvent.VK_F3;
- case NSF4FunctionKey: return KeyEvent.VK_F4;
- case NSF5FunctionKey: return KeyEvent.VK_F5;
- case NSF6FunctionKey: return KeyEvent.VK_F6;
- case NSF7FunctionKey: return KeyEvent.VK_F7;
- case NSF8FunctionKey: return KeyEvent.VK_F8;
- case NSF9FunctionKey: return KeyEvent.VK_F9;
- case NSF10FunctionKey: return KeyEvent.VK_F10;
- case NSF11FunctionKey: return KeyEvent.VK_F11;
- case NSF12FunctionKey: return KeyEvent.VK_F12;
- case NSF13FunctionKey: return KeyEvent.VK_F13;
- case NSF14FunctionKey: return KeyEvent.VK_F14;
- case NSF15FunctionKey: return KeyEvent.VK_F15;
- case NSF16FunctionKey: return KeyEvent.VK_F16;
- case NSF17FunctionKey: return KeyEvent.VK_F17;
- case NSF18FunctionKey: return KeyEvent.VK_F18;
- case NSF19FunctionKey: return KeyEvent.VK_F19;
- case NSF20FunctionKey: return KeyEvent.VK_F20;
- case NSF21FunctionKey: return KeyEvent.VK_F21;
- case NSF22FunctionKey: return KeyEvent.VK_F22;
- case NSF23FunctionKey: return KeyEvent.VK_F23;
- case NSF24FunctionKey: return KeyEvent.VK_F24;
- case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
- case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
- case NSHomeFunctionKey: return KeyEvent.VK_HOME;
- case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
- case NSEndFunctionKey: return KeyEvent.VK_END;
- case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
- case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
- case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
- case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
- case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
- // Not handled:
- // NSSysReqFunctionKey
- // NSBreakFunctionKey
- // NSResetFunctionKey
- case NSStopFunctionKey: return KeyEvent.VK_STOP;
- // Not handled:
- // NSMenuFunctionKey
- // NSUserFunctionKey
- // NSSystemFunctionKey
- // NSPrintFunctionKey
- // NSClearLineFunctionKey
- // NSClearDisplayFunctionKey
- // NSInsertLineFunctionKey
- // NSDeleteLineFunctionKey
- // NSInsertCharFunctionKey
- // NSDeleteCharFunctionKey
- // NSPrevFunctionKey
- // NSNextFunctionKey
- // NSSelectFunctionKey
- // NSExecuteFunctionKey
- // NSUndoFunctionKey
- // NSRedoFunctionKey
- // NSFindFunctionKey
- // NSHelpFunctionKey
- // NSModeSwitchFunctionKey
- default: break;
- }
- }
- if ('a' <= keyChar && keyChar <= 'z') {
- return KeyEvent.VK_A + ( keyChar - 'a' ) ;
+ switch (keyChar) {
+ case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
+ case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
+ case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
+ case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
+ case NSF1FunctionKey: return KeyEvent.VK_F1;
+ case NSF2FunctionKey: return KeyEvent.VK_F2;
+ case NSF3FunctionKey: return KeyEvent.VK_F3;
+ case NSF4FunctionKey: return KeyEvent.VK_F4;
+ case NSF5FunctionKey: return KeyEvent.VK_F5;
+ case NSF6FunctionKey: return KeyEvent.VK_F6;
+ case NSF7FunctionKey: return KeyEvent.VK_F7;
+ case NSF8FunctionKey: return KeyEvent.VK_F8;
+ case NSF9FunctionKey: return KeyEvent.VK_F9;
+ case NSF10FunctionKey: return KeyEvent.VK_F10;
+ case NSF11FunctionKey: return KeyEvent.VK_F11;
+ case NSF12FunctionKey: return KeyEvent.VK_F12;
+ case NSF13FunctionKey: return KeyEvent.VK_F13;
+ case NSF14FunctionKey: return KeyEvent.VK_F14;
+ case NSF15FunctionKey: return KeyEvent.VK_F15;
+ case NSF16FunctionKey: return KeyEvent.VK_F16;
+ case NSF17FunctionKey: return KeyEvent.VK_F17;
+ case NSF18FunctionKey: return KeyEvent.VK_F18;
+ case NSF19FunctionKey: return KeyEvent.VK_F19;
+ case NSF20FunctionKey: return KeyEvent.VK_F20;
+ case NSF21FunctionKey: return KeyEvent.VK_F21;
+ case NSF22FunctionKey: return KeyEvent.VK_F22;
+ case NSF23FunctionKey: return KeyEvent.VK_F23;
+ case NSF24FunctionKey: return KeyEvent.VK_F24;
+ case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
+ case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
+ case NSHomeFunctionKey: return KeyEvent.VK_HOME;
+ case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
+ case NSEndFunctionKey: return KeyEvent.VK_END;
+ case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
+ case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
+ case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
+ case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
+ case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
+ // Not handled:
+ // NSSysReqFunctionKey
+ // NSBreakFunctionKey
+ // NSResetFunctionKey
+ case NSStopFunctionKey: return KeyEvent.VK_STOP;
+ // Not handled:
+ // NSMenuFunctionKey
+ // NSUserFunctionKey
+ // NSSystemFunctionKey
+ // NSPrintFunctionKey
+ // NSClearLineFunctionKey
+ // NSClearDisplayFunctionKey
+ // NSInsertLineFunctionKey
+ // NSDeleteLineFunctionKey
+ // NSInsertCharFunctionKey
+ // NSDeleteCharFunctionKey
+ // NSPrevFunctionKey
+ // NSNextFunctionKey
+ // NSSelectFunctionKey
+ // NSExecuteFunctionKey
+ // NSUndoFunctionKey
+ // NSRedoFunctionKey
+ // NSFindFunctionKey
+ // NSHelpFunctionKey
+ // NSModeSwitchFunctionKey
}
- return (int) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
- }
+ return (short) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
+ }
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java
deleted file mode 100644
index b9c725fd4..000000000
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2011 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.macosx;
-
-import java.util.List;
-
-import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.DimensionImmutable;
-import javax.media.nativewindow.util.Point;
-
-import jogamp.newt.ScreenImpl;
-
-import com.jogamp.common.util.IntObjectHashMap;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public class MacScreen extends ScreenImpl {
-
- // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
- private static IntObjectHashMap/*<int, DimensionImmutable>*/ scrnIdx2Dimension;
-
- static {
- MacDisplay.initSingleton();
- scrnIdx2Dimension = new IntObjectHashMap();
- scrnIdx2Dimension.setKeyNotFoundValue(null);
- }
-
- public MacScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() { }
-
- private static native int getWidthImpl0(int scrn_idx);
- private static native int getHeightImpl0(int scrn_idx);
-
- private int[] getScreenModeIdx(int idx) {
- // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call)
- DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx);
- if(null == dim) {
- int[] res = getScreenSizeMM0(screen_idx);
- if(null == res || 0 == res.length) {
- return null;
- }
- dim = new Dimension(res[0], res[1]);
- scrnIdx2Dimension.put(screen_idx, dim);
- }
-
- int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight());
- if (null == modeProps || 0 == modeProps.length) {
- return null;
- }
- if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
- throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
- }
- return modeProps;
- }
-
- private int nativeModeIdx;
-
- protected int[] getScreenModeFirstImpl() {
- nativeModeIdx = 0;
- return getScreenModeNextImpl();
- }
-
- protected int[] getScreenModeNextImpl() {
- int[] modeProps = getScreenModeIdx(nativeModeIdx);
- if (null != modeProps && 0 < modeProps.length) {
- nativeModeIdx++;
- return modeProps;
- }
- return null;
- }
-
- protected ScreenMode getCurrentScreenModeImpl() {
- int[] modeProps = getScreenModeIdx(-1);
- if (null != modeProps && 0 < modeProps.length) {
- return ScreenModeUtil.streamIn(modeProps, 0);
- }
- return null;
- }
-
- protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
- final List<ScreenMode> screenModes = this.getScreenModesOrig();
- final int screenModeIdx = screenModes.indexOf(screenMode);
- if(0>screenModeIdx) {
- throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
- }
- final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
- return setScreenMode0(screen_idx, nativeModeIdx);
- }
-
- protected int validateScreenIndex(int idx) {
- return idx;
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(getWidthImpl0(screen_idx));
- virtualSize.setHeight(getHeightImpl0(screen_idx));
- }
-
- private native int[] getScreenSizeMM0(int screen_idx);
- private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM);
- private native boolean setScreenMode0(int screen_index, int mode_idx);
-}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
deleted file mode 100644
index b45c60e69..000000000
--- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.macosx;
-
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
-import javax.media.nativewindow.GraphicsConfigurationFactory;
-import javax.media.nativewindow.NativeWindow;
-import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.SurfaceChangeable;
-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 jogamp.newt.WindowImpl;
-import jogamp.newt.driver.DriverClearFocus;
-import jogamp.newt.driver.DriverUpdatePosition;
-
-import com.jogamp.newt.event.KeyEvent;
-
-public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition {
-
- static {
- MacDisplay.initSingleton();
- }
-
- public MacWindow() {
- }
-
- @Override
- protected void createNativeImpl() {
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen());
- if (null == cfg) {
- throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
- }
- setGraphicsConfiguration(cfg);
- reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
- if (0 == getWindowHandle()) {
- throw new NativeWindowException("Error creating window");
- }
- }
-
- @Override
- protected void closeNativeImpl() {
- try {
- if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
- final long handle = getWindowHandle();
- setWindowHandle(0);
- surfaceHandle = 0;
- sscSurfaceHandle = 0;
- isOffscreenInstance = false;
- if (0 != handle) {
- close0(handle);
- }
- } catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
- e.printStackTrace();
- }
- }
- }
-
- @Override
- protected int lockSurfaceImpl() {
- if(!isOffscreenInstance) {
- return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
- }
- return LOCK_SUCCESS;
- }
-
- @Override
- protected void unlockSurfaceImpl() {
- if(!isOffscreenInstance) {
- unlockSurface0(getWindowHandle());
- }
- }
-
- @Override
- public final long getSurfaceHandle() {
- return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
- }
-
- public void setSurfaceHandle(long surfaceHandle) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
- }
- sscSurfaceHandle = surfaceHandle;
- if (isNativeValid()) {
- if (0 != sscSurfaceHandle) {
- orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
- } /** this is done by recreation!
- else if (isVisible()){
- orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
- } */
- }
- }
-
- public void surfaceSizeChanged(int width, int height) {
- sizeChanged(false, width, height, false);
- }
-
- @Override
- protected void setTitleImpl(final String title) {
- setTitle0(getWindowHandle(), title);
- }
-
- protected void requestFocusImpl(boolean force) {
- if(!isOffscreenInstance) {
- requestFocus0(getWindowHandle(), force);
- } else {
- focusChanged(false, true);
- }
- }
-
- public final void clearFocus() {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance);
- }
- if(!isOffscreenInstance) {
- requestFocusParent0(getWindowHandle());
- } else {
- focusChanged(false, false);
- }
- }
-
- public void updatePosition() {
- final Point pS = getTopLevelLocationOnScreen(getX(), getY());
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS);
- }
- if( !isOffscreenInstance ) {
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
- } // else no offscreen position
- // no native event (fullscreen, some reparenting)
- super.positionChanged(true, getX(), getY());
- }
-
-
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- final Point pS = getTopLevelLocationOnScreen(x, y);
- isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent());
-
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+
- ", offscreenInstance "+isOffscreenInstance+
- ", "+getReconfigureFlagsAsString(null, flags));
- }
-
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) {
- if ( !isOffscreenInstance ) {
- orderOut0(getWindowHandle());
- }
- // no native event ..
- visibleChanged(true, false);
- }
- if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) ||
- 0 != ( FLAG_CHANGE_DECORATION & flags) ||
- 0 != ( FLAG_CHANGE_PARENTING & flags) ||
- 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
- createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags));
- if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; }
- }
- if(x>=0 && y>=0) {
- if( !isOffscreenInstance ) {
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY());
- } // else no offscreen position
- // no native event (fullscreen, some reparenting)
- super.positionChanged(true, x, y);
- }
- if(width>0 && height>0) {
- if( !isOffscreenInstance ) {
- setContentSize0(getWindowHandle(), width, height);
- } // else offscreen size is realized via recreation
- // no native event (fullscreen, some reparenting)
- sizeChanged(true, width, height, false); // incl. validation (incl. repositioning)
- }
- if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) {
- if( !isOffscreenInstance ) {
- orderFront0(getWindowHandle());
- }
- // no native event ..
- visibleChanged(true, true);
- }
- if( !isOffscreenInstance ) {
- setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
- }
- return true;
- }
-
- protected Point getLocationOnScreenImpl(int x, int y) {
- Point p = new Point(x, y);
- // min val is 0
- p.setX(Math.max(p.getX(), 0));
- p.setY(Math.max(p.getY(), 0));
-
- final NativeWindow parent = getParent();
- if( null != parent && 0 != parent.getWindowHandle() ) {
- p.translate(parent.getLocationOnScreen(null));
- }
- return p;
- }
-
- private Point getTopLevelLocationOnScreen(int x, int y) {
- final InsetsImmutable _insets = getInsets(); // zero if undecorated
- // client position -> top-level window position
- x -= _insets.getLeftWidth() ;
- y -= _insets.getTopHeight() ;
- return getLocationOnScreenImpl(x, y);
- }
-
- protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
- }
-
- @Override
- protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
- if(getWidth() != newWidth || getHeight() != newHeight) {
- final Point p0S = getTopLevelLocationOnScreen(getX(), getY());
- setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY());
- }
- super.sizeChanged(defer, newWidth, newHeight, force);
- }
-
- @Override
- protected void positionChanged(boolean defer, int newX, int newY) {
- // passed coordinates are in screen position of the client area
- if(getWindowHandle()!=0) {
- // screen position -> window position
- Point absPos = new Point(newX, newY);
- final NativeWindow parent = getParent();
- if(null != parent) {
- absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) );
- }
- super.positionChanged(defer, absPos.getX(), absPos.getY());
- }
- }
-
- @Override
- protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- if( !isOffscreenInstance ) {
- return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
- } // else may need offscreen solution ? FIXME
- return false;
- }
-
- @Override
- protected boolean confinePointerImpl(final boolean confine) {
- if( !isOffscreenInstance ) {
- return confinePointer0(getWindowHandle(), confine);
- } // else may need offscreen solution ? FIXME
- return false;
- }
-
- @Override
- protected void warpPointerImpl(final int x, final int y) {
- if( !isOffscreenInstance ) {
- warpPointer0(getWindowHandle(), x, y);
- } // else may need offscreen solution ? FIXME
- }
-
- @Override
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we send the key char for the key code on this
- // platform -- we do not get any useful key codes out of the system
- final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar);
- final boolean valid = validateKeyEvent(eventType, modifiers, keyCode);
- if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid);
- if(valid) {
- // only deliver keyChar on key Typed events, harmonizing platform behavior
- keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1;
- super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar);
- }
- }
-
- @Override
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we send the key char for the key code on this
- // platform -- we do not get any useful key codes out of the system
- final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar);
- final boolean valid = validateKeyEvent(eventType, modifiers, keyCode);
- if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid);
- if(valid) {
- // only deliver keyChar on key Typed events, harmonizing platform behavior
- keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1;
- super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar);
- }
- }
-
- private int keyDownModifiers = 0;
- private int keyDownCode = 0;
-
- private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) {
- switch(eventType) {
- case KeyEvent.EVENT_KEY_PRESSED:
- keyDownModifiers = modifiers;
- keyDownCode = keyCode;
- return true;
- case KeyEvent.EVENT_KEY_RELEASED:
- return keyDownModifiers == modifiers && keyDownCode == keyCode;
- case KeyEvent.EVENT_KEY_TYPED:
- final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode;
- keyDownModifiers = 0;
- keyDownCode = 0;
- return matchKeyDown;
- default:
- throw new NativeWindowException("Unexpected key event type " + eventType);
- }
- }
-
-
- //----------------------------------------------------------------------
- // Internals only
- //
-
- private void createWindow(final boolean offscreenInstance, final boolean recreate,
- final PointImmutable pS, final int width, final int height,
- final boolean fullscreen) {
-
- if(0!=getWindowHandle() && !recreate) {
- return;
- }
-
- try {
- if(0!=getWindowHandle()) {
- // save the view .. close the window
- surfaceHandle = changeContentView0(getParentWindowHandle(), getWindowHandle(), 0);
- if(recreate && 0==surfaceHandle) {
- throw new NativeWindowException("Internal Error - recreate, window but no view");
- }
- orderOut0(getWindowHandle());
- close0(getWindowHandle());
- setWindowHandle(0);
- } else {
- surfaceHandle = 0;
- }
- setWindowHandle(createWindow0(getParentWindowHandle(),
- pS.getX(), pS.getY(), width, height,
- (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance),
- fullscreen,
- ((isUndecorated() || offscreenInstance) ?
- NSBorderlessWindowMask :
- NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask),
- NSBackingStoreBuffered,
- getScreen().getIndex(), surfaceHandle));
- if (getWindowHandle() == 0) {
- throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this);
- }
- surfaceHandle = contentView0(getWindowHandle());
- if( offscreenInstance ) {
- orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle());
- } else {
- setTitle0(getWindowHandle(), getTitle());
- }
- } catch (Exception ie) {
- ie.printStackTrace();
- }
- }
-
- protected static native boolean initIDs0();
- private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h,
- boolean opaque, boolean fullscreen, int windowStyle,
- int backingStoreType,
- int screen_idx, long view);
- private native boolean lockSurface0(long window);
- private native void unlockSurface0(long window);
- private native void requestFocus0(long window, boolean force);
- private native void requestFocusParent0(long window);
- /** in case of a child window, it actually only issues orderBack(..) */
- private native void orderOut0(long window);
- private native void orderFront0(long window);
- private native void close0(long window);
- private native void setTitle0(long window, String title);
- private native long contentView0(long window);
- private native long changeContentView0(long parentWindowOrViewHandle, long window, long view);
- private native void setContentSize0(long window, int w, int h);
- private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y);
- private native void setAlwaysOnTop0(long window, boolean atop);
- private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
- 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);
-
- // Window styles
- private static final int NSBorderlessWindowMask = 0;
- private static final int NSTitledWindowMask = 1 << 0;
- private static final int NSClosableWindowMask = 1 << 1;
- private static final int NSMiniaturizableWindowMask = 1 << 2;
- private static final int NSResizableWindowMask = 1 << 3;
-
- // Window backing store types
- private static final int NSBackingStoreRetained = 0;
- private static final int NSBackingStoreNonretained = 1;
- private static final int NSBackingStoreBuffered = 2;
-
- private volatile long surfaceHandle = 0;
- private long sscSurfaceHandle = 0;
- private boolean isOffscreenInstance = false;
-
-}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
new file mode 100644
index 000000000..4f3cc691b
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2011 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.macosx;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ private MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, int crt_idx, int mode_idx) {
+ final int[] modeProps = getMonitorMode0(crt_idx, mode_idx);
+ final MonitorMode res;
+ if (null == modeProps || 0 >= modeProps.length) {
+ res = null;
+ } else {
+ res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
+ }
+ return res;
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int crtIdx = 0;
+ int modeIdx = 0;
+ ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ do {
+ final MonitorMode mode = getMonitorModeImpl(cache, crtIdx, modeIdx);
+ if( null != mode ) {
+ supportedModes.getOrAdd(mode);
+ // next mode on same monitor
+ modeIdx++;
+ } else if( 0 < modeIdx ) {
+ // end of monitor modes - got at least one mode
+ final MonitorMode currentMode = getMonitorModeImpl(cache, crtIdx, -1);
+ if ( null == currentMode ) {
+ throw new InternalError("Could not gather current mode of device "+crtIdx+", but gathered "+modeIdx+" modes");
+ }
+ final int[] monitorProps = getMonitorProps0(crtIdx);
+ if ( null == monitorProps ) {
+ throw new InternalError("Could not gather device "+crtIdx+", but gathered "+modeIdx+" modes");
+ }
+ // merge monitor-props + supported modes
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
+
+ // next monitor, 1st mode
+ supportedModes= new ArrayHashSet<MonitorMode>();
+ crtIdx++;
+ modeIdx=0;
+ } else {
+ // end of monitor
+ break;
+ }
+ } while ( true );
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+ return getMonitorModeImpl(null, monitor.getId(), -1);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation());
+ }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
+ }
+
+ private native int[] getMonitorProps0(int crt_idx);
+ private native int[] getMonitorMode0(int crt_index, int mode_idx);
+ private native boolean setMonitorMode0(int crt_index, int nativeId, int rot);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
new file mode 100644
index 000000000..e2a57debc
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.macosx;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.GraphicsConfigurationFactory;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
+
+import jogamp.nativewindow.macosx.OSXUtil;
+import jogamp.newt.PointerIconImpl;
+import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.DriverClearFocus;
+import jogamp.newt.driver.DriverUpdatePosition;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+
+public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public WindowDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ setGraphicsConfiguration(cfg);
+ reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
+ if (0 == getWindowHandle()) {
+ throw new NativeWindowException("Error creating window");
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ try {
+ if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
+ final long handle = getWindowHandle();
+ visibleChanged(true, false);
+ setWindowHandle(0);
+ surfaceHandle = 0;
+ sscSurfaceHandle = 0;
+ isOffscreenInstance = false;
+ if (0 != handle) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ close0( handle );
+ } } );
+ }
+ } catch (Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ protected int lockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return LOCK_SUCCESS;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if( 0 != v && 0 != w ) {
+ return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
+ }
+ return LOCK_SURFACE_NOT_READY;
+ }
+
+ @Override
+ protected void unlockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if(0 != w && 0 != v) {
+ if( !unlockSurface0(w, v) ) {
+ throw new NativeWindowException("Failed to unlock surface, probably not locked!");
+ }
+ }
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
+ }
+
+ @Override
+ public void setSurfaceHandle(long surfaceHandle) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ }
+ sscSurfaceHandle = surfaceHandle;
+ if (isNativeValid()) {
+ if (0 != sscSurfaceHandle) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } /** this is done by recreation!
+ else if (isVisible()){
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } */
+ }
+ }
+
+ @Override
+ protected void setTitleImpl(final String title) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setTitle0(getWindowHandle(), title);
+ } } );
+ }
+
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ final boolean _isFullscreen = isFullscreen();
+ final boolean _isOffscreenInstance = isOffscreenInstance;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
+ }
+ if(!_isOffscreenInstance) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ requestFocus0(getWindowHandle(), force);
+ if(_isFullscreen) {
+ // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
+ focusChanged(false, true);
+ }
+ } } );
+ } else {
+ focusChanged(false, true);
+ }
+ }
+
+ @Override
+ public final void clearFocus() {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
+ }
+ if(!isOffscreenInstance) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ resignFocus0(getWindowHandle());
+ } } );
+ } else {
+ focusChanged(false, false);
+ }
+ }
+
+ private boolean useParent(NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
+
+ @Override
+ public void updatePosition(int x, int y) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ final int pX=parent.getX(), pY=parent.getY();
+ final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
+ }
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(handle, p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ }
+ }
+
+ @Override
+ protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent && ( getWidth() != newWidth || getHeight() != newHeight ) ) {
+ final int x=getX(), y=getY();
+ final Point p0S = getLocationOnScreenImpl(x, y, parent, useParent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos");
+ }
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ }
+ }
+ super.sizeChanged(defer, newWidth, newHeight, force);
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
+ final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
+ isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
+ final PointImmutable pClientLevelOnSreen;
+ if( isOffscreenInstance ) {
+ pClientLevelOnSreen = new Point(0, 0);
+ } else {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent ) {
+ pClientLevelOnSreen = getLocationOnScreenImpl(x, y, parent, useParent);
+ } else {
+ pClientLevelOnSreen = new Point(x, y);
+ }
+ }
+
+ if(DEBUG_IMPLEMENTATION) {
+ final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
+ final NativeWindow pWin = getParent();
+ final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
+ System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPos "+pClientLevelOnSreen+" - "+width+"x"+height+
+ ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
+ ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
+ ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
+ ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
+ ", ioi: "+_isOffscreenInstance+
+ ") -> "+isOffscreenInstance+
+ "\n\t, "+getReconfigureFlagsAsString(null, flags));
+ // Thread.dumpStack();
+ }
+
+ final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
+
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
+ if ( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0(getWindowHandle());
+ visibleChanged(true, false);
+ } } );
+ } else {
+ visibleChanged(true, false);
+ }
+ }
+ if( 0 == getWindowHandle() && setVisible ||
+ 0 != ( FLAG_CHANGE_DECORATION & flags) ||
+ 0 != ( FLAG_CHANGE_PARENTING & flags) ||
+ 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
+ if(isOffscreenInstance) {
+ createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
+ } else {
+ createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
+ 0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+ }
+ } else {
+ if( width>0 && height>0 ) {
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
+ } } );
+ } // else offscreen size is realized via recreation
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ sizeChanged(true, width, height, false);
+ }
+ if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ orderFront0(getWindowHandle());
+ visibleChanged(true, true);
+ } } );
+ } else {
+ visibleChanged(true, true);
+ }
+ }
+ if( !isOffscreenInstance ) {
+ setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+ }
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow reconfig.X: clientPos "+pClientLevelOnSreen+", "+width+"x"+height+" -> clientPos "+getLocationOnScreenImpl(0, 0)+", insets: "+getInsets());
+ }
+ return true;
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(int x, int y) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ return getLocationOnScreenImpl(x, y, parent, useParent);
+ }
+
+ private Point getLocationOnScreenImpl(final int x, final int y, final NativeWindow parent, final boolean useParent) {
+ if( !useParent && !isOffscreenInstance && 0 != surfaceHandle) {
+ return OSXUtil.GetLocationOnScreen(surfaceHandle, true, x, y);
+ }
+
+ final Point p = new Point(x, y);
+ if( useParent ) {
+ p.translate( parent.getLocationOnScreen(null) );
+ }
+ return p;
+ }
+
+ @Override
+ protected void updateInsetsImpl(Insets insets) {
+ // nop - using event driven insetsChange(..)
+ }
+
+ /** Callback for native screen position change event of the client area. */
+ protected void screenPositionChanged(boolean defer, int newX, int newY) {
+ // passed coordinates are in screen position of the client area
+ if(getWindowHandle()!=0) {
+ final NativeWindow parent = getParent();
+ if( null == parent || isOffscreenInstance ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ positionChanged(defer, newX, newY);
+ } else {
+ // screen position -> rel child window position
+ Point absPos = new Point(newX, newY);
+ Point parentOnScreen = parent.getLocationOnScreen(null);
+ absPos.translate( parentOnScreen.scale(-1, -1) );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
+ }
+ positionChanged(defer, absPos.getX(), absPos.getY());
+ }
+ } else if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ }
+
+ @Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ if( !isOffscreenInstance ) {
+ final long piHandle = null != pi ? pi.validatedHandle() : 0;
+ OSXUtil.RunOnMainThread(true, new Runnable() { // waitUntildone due to PointerIconImpl's Lifecycle !
+ @Override
+ public void run() {
+ setPointerIcon0(getWindowHandle(), piHandle);
+ } } );
+ }
+ }
+
+ @Override
+ protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
+ if( !isOffscreenInstance ) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible);
+ } } );
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean confinePointerImpl(final boolean confine) {
+ if( !isOffscreenInstance ) {
+ confinePointer0(getWindowHandle(), confine);
+ return true;
+ } // else may need offscreen solution ? FIXME
+ return false;
+ }
+
+ @Override
+ protected void warpPointerImpl(final int x, final int y) {
+ if( !isOffscreenInstance ) {
+ warpPointer0(getWindowHandle(), x, y);
+ } // else may need offscreen solution ? FIXME
+ }
+
+ @Override
+ public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ @Override
+ public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, short _keySym, char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ protected final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short _keyCode, char keyChar, char keySymChar) {
+ // Note that we send the key char for the key code on this
+ // platform -- we do not get any useful key codes out of the system
+ final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
+ final short keySym;
+ {
+ short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
+ keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
+ }
+ /**
+ {
+ final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
+ ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
+ ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
+ ", mods "+toHexString(modifiers)+
+ ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
+ ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
+ } */
+
+ // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
+ switch(eventType) {
+ case KeyEvent.EVENT_KEY_RELEASED:
+ if( isKeyCodeTracked(keyCode) ) {
+ setKeyPressed(keyCode, false);
+ }
+ break;
+ case KeyEvent.EVENT_KEY_PRESSED:
+ if( isKeyCodeTracked(keyCode) ) {
+ if( setKeyPressed(keyCode, true) ) {
+ // key was already pressed
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
+ }
+ }
+ break;
+ }
+ super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ private void createWindow(final boolean offscreenInstance, final boolean recreate,
+ final PointImmutable pS, final int width, final int height,
+ final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
+
+ final long parentWinHandle = getParentWindowHandle();
+ final long preWinHandle = getWindowHandle();
+
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
+ ": offscreen "+offscreenInstance+", recreate "+recreate+
+ ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
+ ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
+ ", surfaceHandle "+toHexString(surfaceHandle));
+ // Thread.dumpStack();
+ }
+
+ try {
+ if( 0 != preWinHandle ) {
+ setWindowHandle(0);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
+ }
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ @Override
+ public void run() {
+ changeContentView0(parentWinHandle, preWinHandle, 0);
+ close0( preWinHandle );
+ } } );
+ } else {
+ if( 0 != surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
+ }
+ surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, fullscreen);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
+ }
+ }
+
+ final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
+ ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
+ NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
+ NSBackingStoreBuffered, surfaceHandle);
+ if ( newWin == 0 ) {
+ throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
+ }
+ setWindowHandle( newWin );
+
+ final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
+ // Blocking initialization on main-thread!
+ OSXUtil.RunOnMainThread(true, new Runnable() {
+ @Override
+ public void run() {
+ initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height,
+ isOpaque, visible && !offscreenInstance, surfaceHandle);
+ if( offscreenInstance ) {
+ orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
+ } else {
+ setTitle0(newWin, getTitle());
+ setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
+ }
+ visibleChanged(true, visible);
+ } } );
+ } catch (Exception ie) {
+ ie.printStackTrace();
+ }
+ }
+
+ protected static native boolean initIDs0();
+ private native long createView0(int x, int y, int w, int h, boolean fullscreen);
+ private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
+ /** Must be called on Main-Thread */
+ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, boolean opaque, boolean visible, long view);
+ private native boolean lockSurface0(long window, long view);
+ private native boolean unlockSurface0(long window, long view);
+ /** Must be called on Main-Thread */
+ private native void requestFocus0(long window, boolean force);
+ /** Must be called on Main-Thread */
+ private native void resignFocus0(long window);
+ /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
+ private native void orderOut0(long window);
+ /** Must be called on Main-Thread */
+ private native void orderFront0(long window);
+ /** Must be called on Main-Thread */
+ private native void close0(long window);
+ /** Must be called on Main-Thread */
+ private native void setTitle0(long window, String title);
+ private native long contentView0(long window);
+ /** Must be called on Main-Thread */
+ private native void changeContentView0(long parentWindowOrView, long window, long view);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
+ /** Must be called on Main-Thread */
+ private native void setAlwaysOnTop0(long window, boolean atop);
+ private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
+ private static native void setPointerIcon0(long windowHandle, long handle);
+ private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
+ private static native void confinePointer0(long windowHandle, boolean confine);
+ private static native void warpPointer0(long windowHandle, int x, int y);
+
+ // Window styles
+ private static final int NSBorderlessWindowMask = 0;
+ private static final int NSTitledWindowMask = 1 << 0;
+ private static final int NSClosableWindowMask = 1 << 1;
+ private static final int NSMiniaturizableWindowMask = 1 << 2;
+ private static final int NSResizableWindowMask = 1 << 3;
+
+ // Window backing store types
+ private static final int NSBackingStoreRetained = 0;
+ private static final int NSBackingStoreNonretained = 1;
+ private static final int NSBackingStoreBuffered = 2;
+
+ private volatile long surfaceHandle = 0;
+ private long sscSurfaceHandle = 0;
+ private boolean isOffscreenInstance = false;
+
+}
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..551929b8d
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
@@ -0,0 +1,89 @@
+/**
+ * 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 javax.media.nativewindow.util.PixelFormat;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+public class JoglUtilPNGIcon {
+
+ public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
+ final PNGPixelRect[] images = new PNGPixelRect[resources.resourceCount()];
+ data_size[0] = 0;
+ for(int i=0; i<resources.resourceCount(); i++) {
+ final URLConnection urlConn = resources.resolve(i);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ data_size[0] += 2 + image.getSize().getWidth() * image.getSize().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 PNGPixelRect image1 = images[i];
+ final int width = image1.getSize().getWidth();
+ final int height = image1.getSize().getHeight();
+ if( is64Bit ) {
+ buffer.putLong(width);
+ buffer.putLong(height);
+ } else {
+ buffer.putInt(width);
+ buffer.putInt(height);
+ }
+ final ByteBuffer bb = image1.getPixels();
+ final int stride = image1.getStride();
+ for(int y=0; y<height; y++) {
+ int bbOff = y * stride;
+ for(int x=0; x<width; x++) {
+ long pixel;
+ pixel = ( 0xffL & bb.get(bbOff++) ); // B
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A
+ if( is64Bit ) {
+ buffer.putLong(pixel);
+ } else {
+ buffer.putInt((int)pixel);
+ }
+ }
+ }
+ }
+ 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
new file mode 100644
index 000000000..a30431788
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+package jogamp.newt.driver.windows;
+
+import java.net.URLConnection;
+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 javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.util.PixelFormat;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+public class DisplayDriver extends DisplayImpl {
+
+ private static final String newtClassBaseName = "_newt_clazz" ;
+ private static final long[] defaultIconHandles;
+ private static RegisteredClassFactory sharedClassFactory;
+
+ static {
+ NEWTJNILibLoader.loadNEWT();
+ {
+ long[] _defaultIconHandle = { 0, 0 };
+ if( DisplayImpl.isPNGUtilAvailable() ) {
+ try {
+ final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
+ {
+ final URLConnection urlConn = iconRes.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
+ }
+ {
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ defaultIconHandles = _defaultIconHandle;
+ }
+ sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowDriver.getNewtWndProc0(),
+ false /* useDummyDispatchThread */, defaultIconHandles[0], defaultIconHandles[1]);
+
+ if (!WindowDriver.initIDs0(RegisteredClassFactory.getHInstance())) {
+ throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs");
+ }
+ }
+
+ public static void initSingleton() {
+ // just exist to ensure static init has been run
+ }
+
+ protected static long getHInstance() {
+ return RegisteredClassFactory.getHInstance();
+ }
+
+ private RegisteredClass sharedClass;
+
+ public DisplayDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ sharedClass = sharedClassFactory.getSharedClass();
+ aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
+
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ sharedClassFactory.releaseSharedClass();
+ aDevice.close();
+ }
+
+ @Override
+ protected void dispatchMessagesNative() {
+ DispatchMessages0();
+ }
+
+ protected String getWindowClassName() {
+ return sharedClass.getName();
+ }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createBGRA8888Icon0(pixels, width, height, true, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) {
+ destroyIcon0(piHandle);
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ private static native void DispatchMessages0();
+
+ static long createBGRA8888Icon0(Buffer pixels, int width, int height, boolean isCursor, int hotX, int hotY) {
+ if( null == pixels ) {
+ throw new IllegalArgumentException("data buffer/size");
+ }
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createBGRA8888Icon0(
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, isCursor, hotX, hotY);
+ }
+ private static native long createBGRA8888Icon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, 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/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
new file mode 100644
index 000000000..e789b995f
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+package jogamp.newt.driver.windows;
+
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.util.Rectangle;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.newt.Screen;
+
+public class ScreenDriver extends ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ if( Screen.DEBUG ) {
+ dumpMonitorInfo0();
+ }
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ }
+
+ private final String getAdapterName(int crt_idx) {
+ return getAdapterName0(crt_idx);
+ }
+ private final String getActiveMonitorName(String adapterName, int monitor_idx) {
+ return getActiveMonitorName0(adapterName, monitor_idx);
+ }
+
+ private final MonitorMode getMonitorModeImpl(MonitorModeProps.Cache cache, String adapterName, int crtModeIdx) {
+ if( null == adapterName ) {
+ return null;
+ }
+ final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+ final int[] modeProps = null != activeMonitorName ? getMonitorMode0(adapterName, crtModeIdx) : null;
+ if ( null == modeProps || 0 >= modeProps.length) {
+ return null;
+ }
+ return MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
+ }
+
+ @Override
+ protected void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ int crtIdx = 0;
+ ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
+ String adapterName = getAdapterName(crtIdx);
+ while( null != adapterName ) {
+ int crtModeIdx = 0;
+ MonitorMode mode;
+ do {
+ mode = getMonitorModeImpl(cache, adapterName, crtModeIdx);
+ if( null != mode ) {
+ supportedModes.getOrAdd(mode);
+ // next mode on same monitor
+ crtModeIdx++;
+ }
+ } while( null != mode);
+ if( 0 < crtModeIdx ) {
+ // has at least one mode -> add device
+ final MonitorMode currentMode = getMonitorModeImpl(cache, adapterName, -1);
+ if ( null != currentMode ) { // enabled
+ final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx);
+ // merge monitor-props + supported modes
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
+
+ // next monitor, 1st mode
+ supportedModes= new ArrayHashSet<MonitorMode>();
+ }
+ }
+ crtIdx++;
+ adapterName = getAdapterName(crtIdx);
+ }
+ }
+
+ @Override
+ protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) {
+ final String adapterName = getAdapterName(monitor.getId());
+ if( null != adapterName ) {
+ final String activeMonitorName = getActiveMonitorName(adapterName, 0);
+ if( null != activeMonitorName ) {
+ final int[] monitorProps = getMonitorDevice0(adapterName, monitor.getId());
+ int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+ return new Rectangle(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(MonitorDevice monitor) {
+ return getMonitorModeImpl(null, getAdapterName(monitor.getId()), -1);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(MonitorDevice monitor, MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(),
+ -1, -1, // no fixed position!
+ mode.getSurfaceSize().getResolution().getWidth(),
+ mode.getSurfaceSize().getResolution().getHeight(),
+ mode.getSurfaceSize().getBitsPerPixel(),
+ (int)mode.getRefreshRate(), // simply cut-off, orig is int
+ mode.getFlags(),
+ mode.getRotation());
+ }
+
+ @Override
+ protected int validateScreenIndex(int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(Rectangle vOriginSize) {
+ vOriginSize.set(getVirtualOriginX0(), getVirtualOriginY0(), getVirtualWidthImpl0(), getVirtualHeightImpl0());
+ }
+
+ // Native calls
+ private native int getVirtualOriginX0();
+ private native int getVirtualOriginY0();
+ private native int getVirtualWidthImpl0();
+ private native int getVirtualHeightImpl0();
+
+ private static native void dumpMonitorInfo0();
+ private native String getAdapterName0(int crt_index);
+ private native String getActiveMonitorName0(String adapterName, int crtModeIdx);
+ private native int[] getMonitorMode0(String adapterName, int crtModeIdx);
+ private native int[] getMonitorDevice0(String adapterName, int monitor_index);
+ private native boolean setMonitorMode0(int monitor_index, int x, int y, int width, int height, int bits, int freq, int flags, int rot);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index a30aa133c..a48fe2f62 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,38 +29,45 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.windows;
+import java.nio.ByteBuffer;
+
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.newt.PointerIconImpl;
import jogamp.newt.WindowImpl;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseEvent.PointerType;
+
+public class WindowDriver extends WindowImpl {
-public class WindowsWindow extends WindowImpl {
+ static {
+ DisplayDriver.initSingleton();
+ }
private long hmon;
private long hdc;
private long hdc_old;
private long windowHandleClose;
- static {
- WindowsDisplay.initSingleton();
- }
-
- public WindowsWindow() {
+ public WindowDriver() {
}
@Override
@@ -68,31 +75,37 @@ public class WindowsWindow extends WindowImpl {
if (0 != hdc) {
throw new InternalError("surface not released");
}
- hdc = GDI.GetDC(getWindowHandle());
- hmon = MonitorFromWindow0(getWindowHandle());
-
+ final long hWnd = getWindowHandle();
+ hdc = GDI.GetDC(hWnd);
+
// return ( 0 == hdc ) ? LOCK_SURFACE_NOT_READY : ( hdc_old != hdc ) ? LOCK_SURFACE_CHANGED : LOCK_SUCCESS ;
- if( 0 == hdc ) {
+ if( 0 == hdc ) {
return LOCK_SURFACE_NOT_READY;
}
+ hmon = MonitorFromWindow0(hWnd);
+
+ // Let's not trigger on HDC change, GLDrawableImpl.'s destroy/create is a nop here anyways.
+ // FIXME: Validate against EGL surface creation: ANGLE uses HWND -> fine!
+ return LOCK_SUCCESS;
+
+ /**
if( hdc_old == hdc ) {
return LOCK_SUCCESS;
}
- if(DEBUG_IMPLEMENTATION) {
+ if(DEBUG_IMPLEMENTATION) {
System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc));
// Thread.dumpStack();
}
- return LOCK_SURFACE_CHANGED;
+ return LOCK_SURFACE_CHANGED; */
}
@Override
protected void unlockSurfaceImpl() {
- if (0 == hdc) {
- throw new InternalError("surface not acquired");
+ if (0 != hdc) {
+ GDI.ReleaseDC(getWindowHandle(), hdc);
+ hdc_old = hdc;
+ hdc=0;
}
- GDI.ReleaseDC(getWindowHandle(), hdc);
- hdc_old = hdc;
- hdc=0;
}
@Override
@@ -117,55 +130,49 @@ public class WindowsWindow extends WindowImpl {
return false;
}
+ @Override
protected void createNativeImpl() {
- final WindowsScreen screen = (WindowsScreen) getScreen();
- final WindowsDisplay display = (WindowsDisplay) screen.getDisplay();
- final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen());
+ final ScreenDriver screen = (ScreenDriver) getScreen();
+ final DisplayDriver display = (DisplayDriver) screen.getDisplay();
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
if (null == cfg) {
throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
}
setGraphicsConfiguration(cfg);
- final int flags = getReconfigureFlags(0, true) &
+ final VersionNumber winVer = Platform.getOSVersionNumber();
+ final int flags = getReconfigureFlags(0, true) &
( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
- setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
- getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags));
- if (getWindowHandle() == 0) {
+ final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
+ winVer.getMajor(), winVer.getMinor(),
+ getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags);
+ if ( 0 == _windowHandle ) {
throw new NativeWindowException("Error creating window");
}
- windowHandleClose = getWindowHandle();
- addMouseListener(new MouseTracker());
-
+ setWindowHandle(_windowHandle);
+ windowHandleClose = _windowHandle;
+
if(DEBUG_IMPLEMENTATION) {
Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+
" (Parent HWND "+toHexString(getParentWindowHandle())+
- ") : HWND "+toHexString(getWindowHandle())+", "+Thread.currentThread());
+ ") : HWND "+toHexString(_windowHandle)+", "+Thread.currentThread());
e.printStackTrace();
}
}
-
- class MouseTracker extends MouseAdapter {
- public void mouseEntered(MouseEvent e) {
- WindowsWindow.trackPointerLeave0(WindowsWindow.this.getWindowHandle());
- }
- }
+ @Override
protected void closeNativeImpl() {
- if (hdc != 0) {
- if(windowHandleClose != 0) {
+ if( 0 != windowHandleClose ) {
+ if ( 0 != hdc ) {
try {
GDI.ReleaseDC(windowHandleClose, hdc);
} catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
+ if(DEBUG_IMPLEMENTATION) {
Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
e.printStackTrace();
}
}
}
- hdc = 0;
- hdc_old = 0;
- }
- if(windowHandleClose != 0) {
try {
GDI.DestroyWindow(windowHandleClose);
} catch (Throwable t) {
@@ -173,25 +180,27 @@ public class WindowsWindow 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;
}
+ @Override
protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("WindowsWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
getReconfigureFlagsAsString(null, flags));
}
-
+
if(0 == ( FLAG_IS_UNDECORATED & flags)) {
final InsetsImmutable i = getInsets();
-
+
// client position -> top-level window position
x -= i.getLeftWidth() ;
y -= i.getTopHeight() ;
-
+
if(0<width && 0<height) {
// client size -> top-level window size
width += i.getTotalWidth();
@@ -199,13 +208,14 @@ public class WindowsWindow extends WindowImpl {
}
}
reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags);
-
+
if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
- visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+ visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
}
return true;
}
+ @Override
protected void requestFocusImpl(boolean force) {
requestFocus0(getWindowHandle(), force);
}
@@ -216,34 +226,42 @@ public class WindowsWindow extends WindowImpl {
}
@Override
+ protected void setPointerIconImpl(final PointerIconImpl pi) {
+ setPointerIcon0(getWindowHandle(), null != pi ? pi.validatedHandle() : 0);
+ }
+
+ @Override
protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- final Boolean[] res = new Boolean[] { Boolean.FALSE };
-
+ final boolean[] res = new boolean[] { false };
+
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
- res[0] = Boolean.valueOf(setPointerVisible0(getWindowHandle(), pointerVisible));
+ res[0] = setPointerVisible0(getWindowHandle(), pointerVisible);
}
});
- return res[0].booleanValue();
+ return res[0];
}
@Override
protected boolean confinePointerImpl(final boolean confine) {
final Boolean[] res = new Boolean[] { Boolean.FALSE };
-
+
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
final Point p0 = getLocationOnScreenImpl(0, 0);
- res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine,
+ res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine,
p0.getX(), p0.getY(), p0.getX()+getWidth(), p0.getY()+getHeight()));
}
});
return res[0].booleanValue();
}
-
+
@Override
- protected void warpPointerImpl(final int x, final int y) {
+ protected void warpPointerImpl(final int x, final int y) {
this.runOnEDTIfAvail(true, new Runnable() {
+ @Override
public void run() {
final Point sPos = getLocationOnScreenImpl(x, y);
warpPointer0(getWindowHandle(), sPos.getX(), sPos.getY());
@@ -251,54 +269,106 @@ public class WindowsWindow extends WindowImpl {
});
return;
}
-
+
+ @Override
protected Point getLocationOnScreenImpl(int x, int y) {
return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y);
}
+ @Override
protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
+ // nop - using event driven insetsChange(..)
}
-
- private final int validateKeyCode(int eventType, int keyCode) {
+
+ //
+ // PointerEvent Handling
+ //
+ /**
+ * Send multiple-pointer {@link MouseEvent.PointerType#TouchScreen} event to be directly consumed
+ * <p>
+ * Assumes non normal pointer names and rotation/scroll will be determined by a gesture handler.
+ * </p>
+ * <p>
+ * See {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, boolean, int[], int[], int[], float[], float, float[], float)}
+ * for details.
+ * </p>
+ */
+ public final void sendTouchScreenEvent(short eventType, int modifiers,
+ int pActionIdx, int[] pNames,
+ int[] pX, int[] pY, float[] pPressure, float maxPressure) {
+ final int pCount = pNames.length;
+ final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount];
+ for(int i=pCount-1; i>=0; i--) { pTypes[i] = PointerType.TouchScreen; }
+ doPointerEvent(false /*enqueue*/, false /*wait*/,
+ pTypes, eventType, modifiers, pActionIdx, false /*normalPNames*/, pNames,
+ pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/);
+ }
+
+ //
+ // KeyEvent Handling
+ //
+ private short repeatedKey = KeyEvent.VK_UNDEFINED;
+
+ private final boolean handlePressTypedAutoRepeat(boolean isModifierKey, int modifiers, short keyCode, short keySym, char keyChar) {
+ if( setKeyPressed(keyCode, true) ) {
+ // AR: Key was already pressed: Either [enter | within] AR mode
+ final boolean withinAR = repeatedKey == keyCode;
+ repeatedKey = keyCode;
+ if( !isModifierKey ) {
+ // AR: Key was already pressed: Either [enter | within] AR mode
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ if( withinAR ) {
+ // AR: Within AR mode
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+ } // else { AR: Enter AR mode - skip already send PRESSED ; or ALT }
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ final boolean isModifierKey = KeyEvent.isModifierKey(keySym);
+ // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+
+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode, false)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+
+ // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0).
switch(eventType) {
- case KeyEvent.EVENT_KEY_PRESSED:
- lastPressedKeyCode = keyCode;
+ case KeyEvent.EVENT_KEY_RELEASED:
+ if( isKeyCodeTracked(keyCode) ) {
+ if( repeatedKey == keyCode && !isModifierKey ) {
+ // AR out - send out missing PRESSED
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keySym, keyChar);
+ }
+ setKeyPressed(keyCode, false);
+ repeatedKey = KeyEvent.VK_UNDEFINED;
+ }
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
break;
- case KeyEvent.EVENT_KEY_TYPED:
- if(-1==keyCode) {
- keyCode = lastPressedKeyCode;
+ case KeyEvent.EVENT_KEY_PRESSED:
+ if( !handlePressTypedAutoRepeat(isModifierKey, modifiers, keyCode, keySym, keyChar) ) {
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
}
- lastPressedKeyCode = -1;
break;
}
- return keyCode;
- }
- private int lastPressedKeyCode = 0;
-
- @Override
- public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform
- keyCode = validateKeyCode(eventType, keyCode);
- super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
}
-
+
@Override
- public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) {
- // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform
- keyCode = validateKeyCode(eventType, keyCode);
- super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar);
+ public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
}
-
+
//----------------------------------------------------------------------
// Internals only
//
- protected static native boolean initIDs0();
protected static native long getNewtWndProc0();
+ protected static native boolean initIDs0(long hInstance);
- private native long CreateWindow0(long hInstance, String wndClassName, String wndName,
- long parentWindowHandle,
- int x, int y, int width, int height, boolean autoPosition, int flags);
+ 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);
private native long MonitorFromWindow0(long windowHandle);
private native void reconfigureWindow0(long parentWindowHandle, long windowHandle,
int x, int y, int width, int height, int flags);
@@ -307,6 +377,8 @@ public class WindowsWindow 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 void trackPointerLeave0(long windowHandle);
+ 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/windows/WindowsDisplay.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java
deleted file mode 100644
index 225b115e4..000000000
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsDisplay.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.windows;
-
-import jogamp.nativewindow.windows.RegisteredClass;
-import jogamp.nativewindow.windows.RegisteredClassFactory;
-import jogamp.newt.DisplayImpl;
-import jogamp.newt.NEWTJNILibLoader;
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.NativeWindowException;
-
-import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
-
-public class WindowsDisplay extends DisplayImpl {
-
- private static final String newtClassBaseName = "_newt_clazz" ;
- private static RegisteredClassFactory sharedClassFactory;
-
- static {
- NEWTJNILibLoader.loadNEWT();
-
- if (!WindowsWindow.initIDs0()) {
- throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs");
- }
- sharedClassFactory = new RegisteredClassFactory(newtClassBaseName, WindowsWindow.getNewtWndProc0());
- }
-
- public static void initSingleton() {
- // just exist to ensure static init has been run
- }
-
- private RegisteredClass sharedClass;
-
- public WindowsDisplay() {
- }
-
- protected void createNativeImpl() {
- sharedClass = sharedClassFactory.getSharedClass();
- aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
- }
-
- protected void closeNativeImpl() {
- sharedClassFactory.releaseSharedClass();
- }
-
- protected void dispatchMessagesNative() {
- DispatchMessages0();
- }
-
- protected long getHInstance() {
- return sharedClass.getHandle();
- }
-
- protected String getWindowClassName() {
- return sharedClass.getName();
- }
-
- //----------------------------------------------------------------------
- // Internals only
- //
- private static native void DispatchMessages0();
-}
-
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java
deleted file mode 100644
index f8bce9da3..000000000
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-package jogamp.newt.driver.windows;
-
-import javax.media.nativewindow.DefaultGraphicsScreen;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import jogamp.newt.ScreenImpl;
-
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public class WindowsScreen extends ScreenImpl {
-
- static {
- WindowsDisplay.initSingleton();
- }
-
- public WindowsScreen() {
- }
-
- protected void createNativeImpl() {
- aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() {
- }
-
- private int[] getScreenModeIdx(int idx) {
- int[] modeProps = getScreenMode0(screen_idx, idx);
- if (null == modeProps || 0 == modeProps.length) {
- return null;
- }
- if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) {
- throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length);
- }
- return modeProps;
- }
-
- private int nativeModeIdx;
-
- protected int[] getScreenModeFirstImpl() {
- nativeModeIdx = 0;
- return getScreenModeNextImpl();
- }
-
- protected int[] getScreenModeNextImpl() {
- int[] modeProps = getScreenModeIdx(nativeModeIdx);
- if (null != modeProps && 0 < modeProps.length) {
- nativeModeIdx++;
- return modeProps;
- }
- return null;
- }
-
- protected ScreenMode getCurrentScreenModeImpl() {
- int[] modeProps = getScreenModeIdx(-1);
- if (null != modeProps && 0 < modeProps.length) {
- return ScreenModeUtil.streamIn(modeProps, 0);
- }
- return null;
- }
-
- protected boolean setCurrentScreenModeImpl(ScreenMode sm) {
- return setScreenMode0(screen_idx,
- sm.getMonitorMode().getSurfaceSize().getResolution().getWidth(),
- sm.getMonitorMode().getSurfaceSize().getResolution().getHeight(),
- sm.getMonitorMode().getSurfaceSize().getBitsPerPixel(),
- sm.getMonitorMode().getRefreshRate(),
- sm.getRotation());
- }
-
- protected int validateScreenIndex(int idx) {
- return 0; // big-desktop, only one screen available
- }
-
- protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) {
- virtualOrigin.setX(getOriginX0(screen_idx));
- virtualOrigin.setY(getOriginY0(screen_idx));
- virtualSize.setWidth(getWidthImpl0(screen_idx));
- virtualSize.setHeight(getHeightImpl0(screen_idx));
- }
-
- // Native calls
- private native int getOriginX0(int screen_idx);
- private native int getOriginY0(int screen_idx);
- private native int getWidthImpl0(int scrn_idx);
- private native int getHeightImpl0(int scrn_idx);
-
- private native int[] getScreenMode0(int screen_index, int mode_index);
- private native boolean setScreenMode0(int screen_index, int width, int height, int bits, int freq, int rot);
-}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 9464b979b..5c2820dab 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -1,22 +1,22 @@
/*
* Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright (c) 2010 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:
- *
+ *
* - Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
- *
+ *
* - Redistribution 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.
- *
+ *
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
@@ -29,43 +29,46 @@
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ *
*/
package jogamp.newt.driver.x11;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-public class X11Display extends DisplayImpl {
+public class DisplayDriver extends DisplayImpl {
static {
NEWTJNILibLoader.loadNEWT();
- if ( !initIDs0() ) {
+ if ( !initIDs0(X11Util.XERROR_STACKDUMP) ) {
throw new NativeWindowException("Failed to initialize X11Display jmethodIDs");
}
- if (!X11Window.initIDs0()) {
+ if (!WindowDriver.initIDs0()) {
throw new NativeWindowException("Failed to initialize X11Window jmethodIDs");
}
}
- public static void initSingleton() {
- // just exist to ensure static init has been run
- }
-
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
- public X11Display() {
+ public DisplayDriver() {
}
+ @Override
public String validateDisplayName(String name, long handle) {
return X11Util.validateDisplayName(name, handle);
}
@@ -74,98 +77,102 @@ public class X11Display extends DisplayImpl {
* {@inheritDoc}
*
* We use a private non-shared X11 Display instance for EDT window operations and one for exposed animation, eg. OpenGL.
- * <p>
- * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED},
- * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms.
- * </p>
- * <p>
- * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)},
- * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}.
- * </p>
*/
- @SuppressWarnings("unused")
+ @Override
protected void createNativeImpl() {
+ X11Util.setX11ErrorHandler(true, DEBUG ? false : true); // make sure X11 error handler is set
long handle = X11Util.openDisplay(name);
if( 0 == handle ) {
throw new RuntimeException("Error creating display(Win): "+name);
}
- if(USE_SEPARATE_DISPLAY_FOR_EDT) {
- edtDisplayHandle = X11Util.openDisplay(name);
- if( 0 == edtDisplayHandle ) {
- X11Util.closeDisplay(handle);
- throw new RuntimeException("Error creating display(EDT): "+name);
- }
- } else {
- edtDisplayHandle = handle;
- }
+ aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
try {
- CompleteDisplay0(edtDisplayHandle);
+ CompleteDisplay0(aDevice.getHandle());
} catch(RuntimeException e) {
- closeNativeImpl();
+ closeNativeImpl(aDevice);
throw e;
}
-
- // see API doc above!
- if(X11Util.XINITTHREADS_ALWAYS_ENABLED && X11Util.HAS_XLOCKDISPLAY_BUG) {
- aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), false);
- } else {
- aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
- }
}
- protected void closeNativeImpl() {
- DisplayRelease0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom);
+ @Override
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
+ DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
javaObjectAtom = 0;
windowDeleteAtom = 0;
- // closing using ATI driver bug 'same order'
- final long handle = getHandle();
- X11Util.closeDisplay(handle);
- if(handle != edtDisplayHandle) {
- X11Util.closeDisplay(edtDisplayHandle);
- }
- edtDisplayHandle = 0;
+ // kbdHandle = 0;
+ aDevice.close(); // closes X11 display
}
+ @Override
protected void dispatchMessagesNative() {
- if(0 != edtDisplayHandle) {
- DispatchMessages0(edtDisplayHandle, javaObjectAtom, windowDeleteAtom);
+ final AbstractGraphicsDevice _aDevice = aDevice; // aDevice could be pulled by destroy event
+ _aDevice.lock();
+ try {
+ final long handle = _aDevice.getHandle();
+ if(0 != handle) {
+ DispatchMessages0(handle, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
+ }
+ } finally {
+ _aDevice.unlock();
}
}
- protected long getEDTHandle() { return edtDisplayHandle; }
protected long getJavaObjectAtom() { return javaObjectAtom; }
protected long getWindowDeleteAtom() { return windowDeleteAtom; }
-
+ // protected long getKbdHandle() { return kbdHandle; } // XKB disabled for now
+
+ /** 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
+ public final PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon(getHandle(), pixels, width, height, hotX, hotY);
+ }
+
+ @Override
+ protected final void destroyPointerIconImpl(final long displayHandle, long piHandle) {
+ destroyPointerIcon0(displayHandle, piHandle);
+ }
+
//----------------------------------------------------------------------
// Internals only
//
- private static native boolean initIDs0();
+
+ private static native boolean initIDs0(boolean debug);
private native void CompleteDisplay0(long handle);
- private void displayCompleted(long javaObjectAtom, long windowDeleteAtom) {
+ private void displayCompleted(long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */) {
this.javaObjectAtom=javaObjectAtom;
this.windowDeleteAtom=windowDeleteAtom;
+ // this.kbdHandle = kbdHandle; // XKB disabled for now
}
- private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom);
+ private native void DisplayRelease0(long handle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle */); // XKB disabled for now
- private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom);
+ private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
+
+ private static long createPointerIcon(long display, Buffer pixels, int width, int height, int hotX, int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createPointerIcon0(display,
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
+ }
+ private static native long createPointerIcon0(long display, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+
+ private static native void destroyPointerIcon0(long display, long handle);
- /**
- * 2011/06/14 libX11 1.4.2 and libxcb 1.7 bug 20708 - Multithreading Issues w/ OpenGL, ..
- * https://bugs.freedesktop.org/show_bug.cgi?id=20708
- * https://jogamp.org/bugzilla/show_bug.cgi?id=502
- * Affects: Ubuntu 11.04, OpenSuSE 11, ..
- * Workaround: Using a separate X11 Display connection for event dispatching (EDT)
- */
- private final boolean USE_SEPARATE_DISPLAY_FOR_EDT = true;
-
- private long edtDisplayHandle;
-
/** X11 Window delete atom marker used on EDT */
private long windowDeleteAtom;
-
+
/** X11 Window java object property used on EDT */
private long javaObjectAtom;
+
+ /** X11 Keyboard handle used on EDT */
+ // private long kbdHandle; // XKB disabled for now
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
new file mode 100644
index 000000000..8b065d1f0
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
@@ -0,0 +1,86 @@
+/**
+ * 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.x11;
+
+import java.util.List;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public interface RandR {
+ public static final VersionNumber version110 = new VersionNumber(1, 1, 0);
+ public static final VersionNumber version130 = new VersionNumber(1, 3, 0);
+ public static final VersionNumber version140 = new VersionNumber(1, 4, 0);
+
+ VersionNumber getVersion();
+
+ void dumpInfo(final long dpy, final int screen_idx);
+
+ /**
+ * Encapsulate initial device query allowing caching of internal data structures.
+ * Methods covered:
+ * <ul>
+ * <li>{@link #getMonitorDeviceCount(long, ScreenDriver)}</li>
+ * <li>{@link #getAvailableRotations(long, ScreenDriver, int)}</li>
+ * <li>{@link #getMonitorModeProps(long, ScreenDriver, int)}</li>
+ * <li>{@link #getCurrentMonitorModeProps(long, ScreenDriver, int)</li>
+ * <li>{@link #getMonitorDeviceProps(long, ScreenDriver, List, int, MonitorMode)}</li>
+ * </ul>
+ * <p>
+ * Above methods may be called w/o begin/end, in which case no
+ * internal data structures can be cached:
+ * </p>
+ * @param dpy TODO
+ * @param screen TODO
+ * @return TODO
+ */
+ boolean beginInitialQuery(long dpy, ScreenDriver screen);
+ void endInitialQuery(long dpy, ScreenDriver screen);
+
+ int getMonitorDeviceCount(final long dpy, final ScreenDriver screen);
+ int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx);
+ /**
+ *
+ * @param dpy
+ * @param screen
+ * @param mode_idx w/o indexing rotation
+ * @return props w/o actual rotation
+ */
+ int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx);
+ int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx);
+ int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx);
+ int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx);
+ boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+
+ public void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
new file mode 100644
index 000000000..6c22a3fc6
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
@@ -0,0 +1,365 @@
+/**
+ * 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.x11;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+class RandR11 implements RandR {
+ private static final boolean DEBUG = ScreenDriver.DEBUG;
+
+ RandR11() {
+ }
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version110;
+ }
+
+ @Override
+ public void dumpInfo(final long dpy, final int screen_idx) {
+ // NOP
+ }
+
+ private int widthMM=0, heightMM=0;
+ private int modeCount = 0;
+ private int resolutionCount = 0;
+ private int[][] nrates = null; // [nres_number][nrate_number]
+ private int[] idx_rate = null, idx_res = null;
+
+ @Override
+ public boolean beginInitialQuery(long dpy, ScreenDriver screen) {
+ // initialize iterators and static data
+ final int screen_idx = screen.getIndex();
+ resolutionCount = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resolutionCount) {
+ endInitialQuery(dpy, screen);
+ return false;
+ }
+
+ nrates = new int[resolutionCount][];
+ for(int i=0; i<resolutionCount; i++) {
+ nrates[i] = getScreenRates0(dpy, screen_idx, i);
+ if(null==nrates[i] || 0==nrates[i].length) {
+ endInitialQuery(dpy, screen);
+ return false;
+ }
+ }
+
+ for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+ modeCount += nrates[nresIdx].length;
+ }
+
+ idx_rate = new int[modeCount];
+ idx_res = new int[modeCount];
+
+ int modeIdx=0;
+ for(int nresIdx=0; nresIdx < resolutionCount; nresIdx++) {
+ for(int nrateIdx=0; nrateIdx < nrates[nresIdx].length; nrateIdx++) {
+ idx_rate[modeIdx] = nrateIdx;
+ idx_res[modeIdx] = nresIdx;
+ modeIdx++;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void endInitialQuery(long dpy, ScreenDriver screen) {
+ idx_rate=null;
+ idx_res=null;
+ nrates=null;
+ }
+
+ @Override
+ public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+ return 1;
+ }
+
+ @Override
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ final int[] availRotations = getAvailableScreenRotations0(dpy, screen_idx);
+ if(null==availRotations || 0==availRotations.length) {
+ return null;
+ }
+ return availRotations;
+ }
+
+ @Override
+ public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+ if( mode_idx >= modeCount ) {
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+
+ final int nres_index = idx_res[mode_idx];
+ final int nrate_index = idx_rate[mode_idx];
+
+ final int[] res = getScreenResolution0(dpy, screen_idx, nres_index);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+resolutionCount);
+ }
+ if( res[2] > widthMM ) {
+ widthMM = res[2];
+ }
+ if( res[3] > heightMM ) {
+ heightMM = res[3];
+ }
+
+ int rate = nrates[nres_index][nrate_index];
+ if(0>=rate) {
+ rate = ScreenImpl.default_sm_rate;
+ if(DEBUG) {
+ System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+ScreenImpl.default_sm_rate);
+ }
+ }
+
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = ScreenImpl.default_sm_bpp; // bpp n/a in RandR11
+ props[i++] = rate*100; // rate (Hz*100)
+ props[i++] = 0; // flags;
+ props[i++] = nres_index;
+ props[i++] = -1; // rotation placeholder;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return props;
+ }
+
+ @Override
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, final MonitorModeProps.Cache cache, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int[] currentModeProps = getCurrentMonitorModeProps(dpy, screen, crt_idx);
+ if( null == currentModeProps) { // disabled
+ return null;
+ }
+ final MonitorMode currentMode = MonitorModeProps.streamInMonitorMode(null, cache, currentModeProps, 0);
+ final int allModesCount = cache.monitorModes.size();
+ final int[] props = new int[MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES - 1 + allModesCount];
+ int i = 0;
+ props[i++] = props.length;
+ props[i++] = crt_idx;
+ props[i++] = widthMM;
+ props[i++] = heightMM;
+ props[i++] = 0; // rotated viewport x
+ props[i++] = 0; // rotated viewport y
+ props[i++] = currentMode.getRotatedWidth(); // rotated viewport width
+ props[i++] = currentMode.getRotatedHeight(); // rotated viewport height
+ props[i++] = currentMode.getId(); // current mode id
+ props[i++] = currentMode.getRotation();
+ for(int j=0; j<allModesCount; j++) {
+ props[i++] = cache.monitorModes.get(j).getId();
+ }
+ return props;
+ }
+
+ @Override
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return null;
+ }
+ int[] res;
+ final int nres_idx;
+ try {
+ int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resNumber) {
+ return null;
+ }
+
+ nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+ if(0>nres_idx) {
+ return null;
+ }
+ if(nres_idx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+ }
+ res = getScreenResolution0(dpy, screen_idx, nres_idx);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ int[] props = new int[4];
+ int i = 0;
+ props[i++] = 0;
+ props[i++] = 0;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ return props;
+ }
+
+ @Override
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ if( 0 < crt_idx ) {
+ // RandR11 only supports 1 CRT
+ return null;
+ }
+ final int screen_idx = screen.getIndex();
+ long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return null;
+ }
+ int[] res;
+ int rate, rot;
+ final int nres_idx;
+ try {
+ int resNumber = getNumScreenResolutions0(dpy, screen_idx);
+ if(0==resNumber) {
+ return null;
+ }
+
+ nres_idx = getCurrentScreenResolutionIndex0(screenConfigHandle);
+ if(0>nres_idx) {
+ return null;
+ }
+ if(nres_idx>=resNumber) {
+ throw new RuntimeException("Invalid resolution index: ! "+nres_idx+" < "+resNumber);
+ }
+ res = getScreenResolution0(dpy, screen_idx, nres_idx);
+ if(null==res || 0==res.length) {
+ return null;
+ }
+ if(0>=res[0] || 0>=res[1]) {
+ throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_idx+"/"+resNumber);
+ }
+ rate = getCurrentScreenRate0(screenConfigHandle);
+ if(0>rate) {
+ return null;
+ }
+ rot = getCurrentScreenRotation0(screenConfigHandle);
+ if(0>rot) {
+ return null;
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ int[] props = new int[ MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int i = 0;
+ props[i++] = MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL;
+ props[i++] = res[0]; // width
+ props[i++] = res[1]; // height
+ props[i++] = ScreenImpl.default_sm_bpp;
+ props[i++] = rate*100; // rate (Hz*100)
+ props[i++] = 0; // flags;
+ props[i++] = nres_idx; // mode_idx;
+ props[i++] = rot;
+ if( MonitorModeProps.NUM_MONITOR_MODE_PROPERTIES_ALL != i ) {
+ throw new InternalError("XX");
+ }
+ return props;
+ }
+
+ @Override
+ public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) {
+ final long t0 = System.currentTimeMillis();
+ boolean done = false;
+ final int screen_idx = screen.getIndex();
+ long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
+ if(0 == screenConfigHandle) {
+ return Boolean.valueOf(done);
+ }
+ try {
+ final int resId = mode.getId();
+ if(0>resId || resId>=resolutionCount) {
+ throw new RuntimeException("Invalid resolution index: ! 0 < "+resId+" < "+resolutionCount+", "+monitor+", "+mode);
+ }
+ final int f = (int)mode.getRefreshRate(); // simply cut-off, orig is int
+ final int r = mode.getRotation();
+
+ if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resId, f, r) ) {
+ while(!done && System.currentTimeMillis()-t0 < ScreenImpl.SCREEN_MODE_CHANGE_TIMEOUT) {
+ done = setCurrentScreenModePollEnd0(dpy, screen_idx, resId, f, r);
+ if(!done) {
+ try { Thread.sleep(10); } catch (InterruptedException e) { }
+ }
+ }
+ }
+ } finally {
+ freeScreenConfiguration0(screenConfigHandle);
+ }
+ return done;
+ }
+
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport) {
+ // nop
+ }
+
+ /** @return int[] { rot1, .. } */
+ private static native int[] getAvailableScreenRotations0(long display, int screen_index);
+
+ private static native int getNumScreenResolutions0(long display, int screen_index);
+
+ /** @return int[] { width, height, widthmm, heightmm } */
+ private static native int[] getScreenResolution0(long display, int screen_index, int mode_index);
+
+ private static native int[] getScreenRates0(long display, int screen_index, int mode_index);
+
+ private static native long getScreenConfiguration0(long display, int screen_index);
+ private static native void freeScreenConfiguration0(long screenConfiguration);
+
+ private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
+ private static native int getCurrentScreenRate0(long screenConfiguration);
+ private static native int getCurrentScreenRotation0(long screenConfiguration);
+
+ /** needs own Display connection for XRANDR event handling */
+ private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
+ private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
+
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
new file mode 100644
index 000000000..a08741d9e
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
@@ -0,0 +1,274 @@
+/**
+ * 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.x11;
+
+import java.util.Iterator;
+
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.newt.MonitorModeProps;
+
+import com.jogamp.common.util.IntLongHashMap;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+/**
+ * Mapping details:
+ * <pre>
+ * MonitorMode.id == XRR mode-id (not index)
+ * MonitorDevice.id == XRR monitor-idx (not id)
+ * </pre>
+ */
+class RandR13 implements RandR {
+ private static final boolean DEBUG = ScreenDriver.DEBUG;
+
+ RandR13() {
+ }
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version130;
+ }
+
+ @Override
+ public void dumpInfo(final long dpy, final int screen_idx) {
+ long screenResources = getScreenResources0(dpy, screen_idx);
+ if(0 == screenResources) {
+ return;
+ }
+ try {
+ dumpInfo0(dpy, screen_idx, screenResources);
+ } finally {
+ freeScreenResources0(screenResources);
+ }
+ }
+
+ long sessionScreenResources = 0;
+ IntLongHashMap crtInfoHandleMap = null;
+
+ @Override
+ public boolean beginInitialQuery(long dpy, ScreenDriver screen) {
+ final int screen_idx = screen.getIndex();
+ sessionScreenResources = getScreenResources0(dpy, screen_idx);
+ if( 0 != sessionScreenResources ) {
+ crtInfoHandleMap = new IntLongHashMap();
+ crtInfoHandleMap.setKeyNotFoundValue(0);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void endInitialQuery(long dpy, ScreenDriver screen) {
+ if( null != crtInfoHandleMap ) {
+ for(Iterator<IntLongHashMap.Entry> iter = crtInfoHandleMap.iterator(); iter.hasNext(); ) {
+ final IntLongHashMap.Entry entry = iter.next();
+ freeMonitorInfoHandle0(entry.value);
+ }
+ crtInfoHandleMap.clear();
+ crtInfoHandleMap = null;
+ }
+ if( 0 != sessionScreenResources ) {
+ freeScreenResources0( sessionScreenResources );
+ sessionScreenResources = 0;
+ }
+ }
+
+ private final long getScreenResourceHandle(final long dpy, final int screen_idx) {
+ if( 0 != sessionScreenResources ) {
+ return sessionScreenResources;
+ }
+ return getScreenResources0(dpy, screen_idx);
+ }
+ private final void releaseScreenResourceHandle(final long screenResourceHandle) {
+ if( 0 == sessionScreenResources ) {
+ freeScreenResources0( screenResourceHandle );
+ }
+ }
+
+ private final long getMonitorInfoHandle(final long dpy, final int screen_idx, long screenResources, final int monitor_idx) {
+ if( null != crtInfoHandleMap ) {
+ long h = crtInfoHandleMap.get(monitor_idx);
+ if( 0 == h ) {
+ h = getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+ crtInfoHandleMap.put(monitor_idx, h);
+ }
+ return h;
+ } else {
+ return getMonitorInfoHandle0(dpy, screen_idx, screenResources, monitor_idx);
+ }
+ }
+ private final void releaseMonitorInfoHandle(final long monitorInfoHandle) {
+ if( null == crtInfoHandleMap ) {
+ freeMonitorInfoHandle0(monitorInfoHandle);
+ }
+ }
+
+ @Override
+ public int getMonitorDeviceCount(final long dpy, final ScreenDriver screen) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ return getMonitorDeviceCount0(screenResources);
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getAvailableRotations(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ final int[] availRotations = getAvailableRotations0(monitorInfo);
+ if(null==availRotations || 0==availRotations.length) {
+ return null;
+ }
+ return availRotations;
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorModeProps(final long dpy, final ScreenDriver screen, final int mode_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ return getMonitorMode0(screenResources, mode_idx);
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorDevice0(dpy, screenResources, monitorInfo, crt_idx);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorViewport0(monitorInfo);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, crt_idx);
+ try {
+ return getMonitorCurrentMode0(screenResources, monitorInfo);
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ @Override
+ public boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ final boolean res;
+ try {
+ final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
+ try {
+ res = setMonitorMode0(dpy, screenResources, monitorInfo, monitor.getId(), mode.getId(), mode.getRotation(),
+ -1, -1); // no fixed position!
+ } finally {
+ releaseMonitorInfoHandle(monitorInfo);
+ }
+ } finally {
+ releaseScreenResourceHandle(screenResources);
+ }
+ return res;
+ }
+
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
+ final int screen_idx = screen.getIndex();
+ final long screenResources = getScreenResourceHandle(dpy, screen_idx);
+ try {
+ setScreenViewport0(dpy, screen_idx, screenResources, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight());
+ } finally {
+ dumpInfo0(dpy, screen_idx, screenResources);
+ releaseScreenResourceHandle(screenResources);
+ }
+ }
+
+ private static native long getScreenResources0(long display, int screen_index);
+ private static native void freeScreenResources0(long screenResources);
+ private static native void dumpInfo0(long display, int screen_index, long screenResources);
+
+ private static native int getMonitorDeviceCount0(long screenResources);
+
+ private static native long getMonitorInfoHandle0(long display, int screen_index, long screenResources, int monitor_index);
+ private static native void freeMonitorInfoHandle0(long monitorInfoHandle);
+
+ private static native int[] getAvailableRotations0(long monitorInfo);
+ private static native int[] getMonitorViewport0(long monitorInfo);
+ private static native int[] getMonitorCurrentMode0(long monitorInfo);
+
+ private static native int[] getMonitorMode0(long screenResources, int mode_index);
+ private static native int[] getMonitorCurrentMode0(long screenResources, long monitorInfo);
+ private static native int[] getMonitorDevice0(long display, long screenResources, long monitorInfo, int monitor_idx);
+
+ private static native boolean setMonitorMode0(long display, long screenResources, long monitorInfo, int monitor_idx, int mode_id, int rotation, int x, int y);
+ private static native boolean setScreenViewport0(long display, int screen_index, long screenResources, int x, int y, int width, int height);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
new file mode 100644
index 000000000..bef7f60ec
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+package jogamp.newt.driver.x11;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.nativewindow.x11.X11Util;
+import jogamp.newt.Debug;
+import jogamp.newt.DisplayImpl;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.DisplayImpl.DisplayRunnable;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.common.util.VersionNumber;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+
+public class ScreenDriver extends ScreenImpl {
+ protected static final boolean DEBUG_TEST_RANDR13_DISABLED;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_RANDR13_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableRandR13", true);
+
+ DisplayDriver.initSingleton();
+ }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ // validate screen index
+ Long handle = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Long>() {
+ @Override
+ public Long run(long dpy) {
+ return new Long(GetScreen0(dpy, screen_idx));
+ } } );
+ if (handle.longValue() == 0) {
+ throw new RuntimeException("Error creating screen: " + screen_idx);
+ }
+ final X11GraphicsDevice x11dev = (X11GraphicsDevice) getDisplay().getGraphicsDevice();
+ final long dpy = x11dev.getHandle();
+ aScreen = new X11GraphicsScreen(x11dev, screen_idx);
+ {
+ int v[] = getRandRVersion0(dpy);
+ randrVersion = new VersionNumber(v[0], v[1], 0);
+ }
+ {
+ if( !DEBUG_TEST_RANDR13_DISABLED && randrVersion.compareTo(RandR.version130) >= 0 ) {
+ rAndR = new RandR13();
+ } else if( randrVersion.compareTo(RandR.version110) >= 0 ) {
+ rAndR = new RandR11();
+ } else {
+ rAndR = null;
+ }
+ }
+ if( DEBUG ) {
+ System.err.println("RandR "+randrVersion+", "+rAndR);
+ rAndR.dumpInfo(dpy, screen_idx);
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ }
+
+ private VersionNumber randrVersion;
+ private RandR rAndR;
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache) {
+ if( null == rAndR ) { return; }
+ final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+ device.lock();
+ try {
+ if( rAndR.beginInitialQuery(device.getHandle(), this) ) {
+ try {
+ final int crtCount = rAndR.getMonitorDeviceCount(device.getHandle(), this);
+
+ // Gather all available rotations
+ final ArrayHashSet<Integer> availableRotations = new ArrayHashSet<Integer>();
+ for(int i = 0; i < crtCount; i++) {
+ final int[] rotations = rAndR.getAvailableRotations(device.getHandle(), this, i);
+ if( null != rotations ) {
+ final List<Integer> rotationList = new ArrayList<Integer>(rotations.length);
+ for(int j=0; j<rotations.length; j++ ) { rotationList.add(rotations[j]); }
+ availableRotations.addAll(rotationList);
+ }
+ }
+
+ // collect all modes, while injecting all available rotations
+ {
+ int modeIdx = 0;
+ int[] props;
+ do {
+ props = rAndR.getMonitorModeProps(device.getHandle(), this, modeIdx++);
+ if( null != props ) {
+ for(int i = 0; i < availableRotations.size(); i++) {
+ props[MonitorModeProps.IDX_MONITOR_MODE_ROT] = availableRotations.get(i);
+ MonitorModeProps.streamInMonitorMode(null, cache, props, 0);
+ }
+ }
+ } while( null != props);
+ }
+ if( cache.monitorModes.size() > 0 ) {
+ for(int i = 0; i < crtCount; i++) {
+ final int[] monitorProps = rAndR.getMonitorDeviceProps(device.getHandle(), this, cache, i);
+ if( null != monitorProps &&
+ MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ?
+ MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) {
+ MonitorModeProps.streamInMonitorDevice(null, cache, this, monitorProps, 0);
+ }
+ }
+ }
+ } finally {
+ rAndR.endInitialQuery(device.getHandle(), this);
+ }
+ }
+ } finally {
+ device.unlock();
+ }
+ }
+
+ @Override
+ protected Rectangle getNativeMonitorDeviceViewportImpl(MonitorDevice monitor) {
+ final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
+ device.lock();
+ try {
+ int[] viewportProps = rAndR.getMonitorDeviceViewport(device.getHandle(), this, monitor.getId());
+ return new Rectangle(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ if( null == rAndR ) { return null; }
+
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<MonitorMode>() {
+ @Override
+ public MonitorMode run(long dpy) {
+ final int[] currentModeProps = rAndR.getCurrentMonitorModeProps(dpy, ScreenDriver.this, monitor.getId());
+ return MonitorModeProps.streamInMonitorMode(null, null, currentModeProps, 0);
+ } } );
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ if( null == rAndR ) { return false; }
+
+ final long t0 = System.currentTimeMillis();
+ boolean done = runWithOptTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(long dpy) {
+ return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) );
+ }
+ }).booleanValue();
+
+ if(DEBUG || !done) {
+ System.err.println("X11Screen.setCurrentMonitorModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
+ (System.currentTimeMillis()-t0)+"ms; "+monitor.getCurrentMode()+" -> "+mode);
+ }
+ return done;
+ }
+
+ private DisplayImpl.DisplayRunnable<Boolean> xineramaEnabledQueryWithTemp = new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(long dpy) {
+ return new Boolean(X11Util.XineramaIsEnabled(dpy));
+ } };
+
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ final DisplayDriver x11Display = (DisplayDriver) getDisplay();
+ final Boolean r = x11Display.isXineramaEnabled();
+ if( null != r ) {
+ return r.booleanValue() ? 0 : idx;
+ } else {
+ return runWithTempDisplayHandle( xineramaEnabledQueryWithTemp ).booleanValue() ? 0 : idx;
+ }
+ }
+
+ @Override
+ protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) {
+ final RectangleImmutable ov = (RectangleImmutable) getViewport().cloneMutable();
+ /**
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 && getMonitorDevices().size()>0 ) {
+ super.calcVirtualScreenOriginAndSize(vOriginSize);
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: UpdatingViewport "+ov+" -> "+vOriginSize);
+ }
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ rAndR.updateScreenViewport(dpy, ScreenDriver.this, vOriginSize);
+ return null;
+ } } );
+ } else */ {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ vOriginSize.set(0, 0, getWidth0(dpy, screen_idx), getHeight0(dpy, screen_idx));
+ return null;
+ } } );
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: Querying X11: "+ov+" -> "+vOriginSize);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ private final <T> T runWithLockedDisplayDevice(DisplayRunnable<T> action) {
+ return display.runWithLockedDisplayDevice(action);
+ }
+
+ private final <T> T runWithTempDisplayHandle(DisplayRunnable<T> action) {
+ final long displayHandle = X11Util.openDisplay(display.getName());
+ if(0 == displayHandle) {
+ throw new RuntimeException("null device");
+ }
+ T res;
+ try {
+ res = action.run(displayHandle);
+ } finally {
+ X11Util.closeDisplay(displayHandle);
+ }
+ return res;
+ }
+
+ private final <T> T runWithOptTempDisplayHandle(DisplayRunnable<T> action) {
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 ) {
+ return display.runWithLockedDisplayDevice(action);
+ } else {
+ return runWithTempDisplayHandle(action);
+ }
+ }
+
+ private static native long GetScreen0(long dpy, int scrn_idx);
+
+ private static native int getWidth0(long display, int scrn_idx);
+
+ private static native int getHeight0(long display, int scrn_idx);
+
+ private static native int[] getRandRVersion0(long display);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
new file mode 100644
index 000000000..0eda37eac
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 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:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
+ * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
+ * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+ * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
+ * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+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.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;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+
+import com.jogamp.common.nio.Buffers;
+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;
+
+public class WindowDriver extends WindowImpl {
+ private static final String WINDOW_CLASS_NAME = "NewtWindow";
+ private static final int X11_WHEEL_ONE_UP_BUTTON = 4;
+ private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5;
+ 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 {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ 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() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ final ScreenDriver screen = (ScreenDriver) getScreen();
+ final DisplayDriver display = (DisplayDriver) screen.getDisplay();
+ final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
+
+ // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering
+ final long renderDeviceHandle = X11Util.openDisplay(edtDevice.getConnection());
+ if( 0 == renderDeviceHandle ) {
+ throw new RuntimeException("Error creating display(GfxCfg/Render): "+edtDevice.getConnection());
+ }
+ renderDevice = new X11GraphicsDevice(renderDeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
+ final AbstractGraphicsScreen renderScreen = new X11GraphicsScreen(renderDevice, screen.getIndex());
+
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice(), capsRequested);
+ final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, renderScreen, VisualIDHolder.VID_UNDEFINED);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg);
+ }
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ final int visualID = cfg.getVisualID(VIDType.NATIVE);
+ if(VisualIDHolder.VID_UNDEFINED == visualID) {
+ throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg);
+ }
+ setGraphicsConfiguration(cfg);
+ final int flags = getReconfigureFlags(0, true) &
+ ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
+ edtDevice.lock();
+ try {
+ setWindowHandle(CreateWindow(getParentWindowHandle(),
+ edtDevice.getHandle(), screen.getIndex(), visualID,
+ display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
+ defaultIconDataSize, defaultIconData));
+ } finally {
+ edtDevice.unlock();
+ }
+ windowHandleClose = getWindowHandle();
+ if (0 == windowHandleClose) {
+ throw new NativeWindowException("Error creating window");
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ if(0!=windowHandleClose && null!=getScreen() ) {
+ DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
+ edtDevice.lock();
+ try {
+ CloseWindow0(edtDevice.getHandle(), windowHandleClose,
+ display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */); // XKB disabled for now
+ } catch (Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
+ e.printStackTrace();
+ }
+ } finally {
+ edtDevice.unlock();
+ windowHandleClose = 0;
+ }
+ }
+ if(null != renderDevice) {
+ renderDevice.close(); // closes X11 display
+ renderDevice = null;
+ }
+ }
+
+ /**
+ * <p>
+ * X11 Window supports {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isReconfigureFlagSupported(int changeFlags) {
+ return true; // all flags!
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
+ final int _x, _y;
+ final InsetsImmutable _insets;
+ if( 0 == ( FLAG_IS_UNDECORATED & flags) ) {
+ // client position -> top-level window position
+ _insets = getInsets();
+ _x = x - _insets.getLeftWidth() ;
+ _y = y - _insets.getTopHeight() ;
+ } else {
+ _insets = null;
+ _x = x;
+ _y = y;
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+", insets "+_insets+", "+ getReconfigureFlagsAsString(null, flags));
+ }
+ if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags ) ) {
+ if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) {
+ tempFSAlwaysOnTop = true;
+ flags |= FLAG_IS_ALWAYSONTOP;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ } else {
+ tempFSAlwaysOnTop = false;
+ }
+ }
+ final int fflags = flags;
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ _x, _y, width, height, fflags);
+ return null;
+ }
+ });
+ return true;
+ }
+ volatile boolean tempFSAlwaysOnTop = false;
+
+ /**
+ * <p>
+ * Deal w/ tempAlwaysOnTop.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected void focusChanged(boolean defer, boolean focusGained) {
+ if( isNativeValid() && isFullscreen() && tempFSAlwaysOnTop && hasFocus() != focusGained ) {
+ final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), flags);
+ return null;
+ }
+ });
+ }
+ super.focusChanged(defer, focusGained);
+ }
+
+ protected void reparentNotify(long newParentWindowHandle) {
+ if(DEBUG_IMPLEMENTATION) {
+ final long p0 = getParentWindowHandle();
+ System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle));
+ }
+ }
+
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ requestFocus0(dpy, getWindowHandle(), force);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ protected void setTitleImpl(final String title) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ setTitle0(dpy, getWindowHandle(), title);
+ return null;
+ }
+ });
+ }
+
+ @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.validatedHandle() : 0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ });
+ }
+
+ @Override
+ protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(long dpy) {
+ final PointerIconImpl pi = (PointerIconImpl)getPointerIcon();
+ final boolean res;
+ if( pointerVisible && null != pi ) {
+ setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.validatedHandle() : 0);
+ res = true;
+ } else {
+ res = setPointerVisible0(dpy, getWindowHandle(), pointerVisible);
+ }
+ return Boolean.valueOf(res);
+ }
+ }).booleanValue();
+ }
+
+ @Override
+ protected boolean confinePointerImpl(final boolean confine) {
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
+ @Override
+ public Boolean run(long dpy) {
+ return Boolean.valueOf(confinePointer0(dpy, getWindowHandle(), confine));
+ }
+ }).booleanValue();
+ }
+
+ @Override
+ protected void warpPointerImpl(final int x, final int y) {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ @Override
+ public Object run(long dpy) {
+ warpPointer0(dpy, getWindowHandle(), x, y);
+ return null;
+ }
+ });
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
+ return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Point>() {
+ @Override
+ public Point run(long dpy) {
+ return X11Lib.GetRelativeLocation(dpy, getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ }
+ } );
+ }
+
+ @Override
+ protected void updateInsetsImpl(Insets insets) {
+ // nop - using event driven insetsChange(..)
+ }
+
+ @Override
+ protected final void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
+ int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+ switch(eventType) {
+ case MouseEvent.EVENT_MOUSE_PRESSED:
+ switch(button) {
+ case X11_WHEEL_ONE_UP_BUTTON:
+ case X11_WHEEL_ONE_DOWN_BUTTON:
+ case X11_WHEEL_TWO_UP_BUTTON:
+ case X11_WHEEL_TWO_DOWN_BUTTON:
+ // ignore wheel pressed !
+ return;
+ }
+ break;
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ final boolean shiftPressed = 0 != ( modifiers & InputEvent.SHIFT_MASK );
+ switch(button) {
+ case X11_WHEEL_ONE_UP_BUTTON: // vertical scroll up
+ eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ button = 1;
+ rotationXYZ[shiftPressed ? 0 : 1] = 1;
+ break;
+ case X11_WHEEL_ONE_DOWN_BUTTON: // vertical scroll down
+ eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ button = 1;
+ rotationXYZ[shiftPressed ? 0 : 1] = -1;
+ break;
+ case X11_WHEEL_TWO_UP_BUTTON: // horizontal scroll left
+ eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ button = 1;
+ rotationXYZ[0] = 1;
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ case X11_WHEEL_TWO_DOWN_BUTTON: // horizontal scroll right
+ eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+ button = 1;
+ rotationXYZ[0] = -1;
+ modifiers |= InputEvent.SHIFT_MASK;
+ break;
+ }
+ break;
+ }
+ super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
+ }
+
+ /** Called by native TK */
+ protected final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar0, String keyString) {
+ // handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
+ final boolean isModifierKey = KeyEvent.isModifierKey(keyCode);
+ final boolean isAutoRepeat = 0 != ( KeyEvent.AUTOREPEAT_MASK & modifiers );
+ final char keyChar = ( null != keyString ) ? keyString.charAt(0) : keyChar0;
+ // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar0+">/<"+keyChar+">, keyString "+keyString+", mods "+toHexString(modifiers)+
+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isAutoRepeat+", [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+
+ if( !isAutoRepeat || !isModifierKey ) { // ! ( isModifierKey && isAutoRepeat )
+ switch(eventType) {
+ case KeyEvent.EVENT_KEY_PRESSED:
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
+ break;
+
+ case KeyEvent.EVENT_KEY_RELEASED:
+ super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+ @Override
+ public final void enqueueKeyEvent(boolean wait, short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+ private static final String getCurrentThreadName() { return Thread.currentThread().getName(); } // Callback for JNI
+ private static final void dumpStack() { Thread.dumpStack(); } // Callback for JNI
+
+ private final <T> T runWithLockedDisplayDevice(DisplayRunnable<T> action) {
+ return ((DisplayDriver) getScreen().getDisplay()).runWithLockedDisplayDevice(action);
+ }
+
+ protected static native boolean initIDs0();
+
+ private long CreateWindow(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 pixelDataSize, Buffer pixels) {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ if( !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+pixels);
+ }
+ return CreateWindow0(parentWindowHandle, display, screen_index,
+ visualID, javaObjectAtom, windowDeleteAtom,
+ x, y, width, height, autoPosition, flags,
+ pixelDataSize,
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */);
+ }
+ 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 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
+ 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);
+ private static native void warpPointer0(long display, long windowHandle, int x, int y);
+
+ private long windowHandleClose;
+ private X11GraphicsDevice renderDevice;
+}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java
deleted file mode 100644
index 93db854ac..000000000
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-package jogamp.newt.driver.x11;
-
-import java.util.List;
-
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
-
-import jogamp.nativewindow.x11.X11Util;
-import jogamp.newt.DisplayImpl;
-import jogamp.newt.DisplayImpl.DisplayRunnable;
-import jogamp.newt.ScreenImpl;
-
-import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-import com.jogamp.newt.ScreenMode;
-import com.jogamp.newt.util.ScreenModeUtil;
-
-public class X11Screen extends ScreenImpl {
-
- static {
- X11Display.initSingleton();
- }
-
- public X11Screen() {
- }
-
- protected void createNativeImpl() {
- // validate screen index
- Long handle = display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Long>() {
- public Long run(long dpy) {
- return new Long(GetScreen0(dpy, screen_idx));
- } } );
- if (handle.longValue() == 0) {
- throw new RuntimeException("Error creating screen: " + screen_idx);
- }
- aScreen = new X11GraphicsScreen((X11GraphicsDevice) getDisplay().getGraphicsDevice(), screen_idx);
- }
-
- protected void closeNativeImpl() {
- }
-
- private int[] nrotations;
- private int nrotation_index;
- private int nres_number;
- private int nres_index;
- private int[] nrates;
- private int nrate_index;
- private int nmode_number;
-
- protected int[] getScreenModeFirstImpl() {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<int[]>() {
- public int[] run(long dpy) {
- // initialize iterators and static data
- nrotations = getAvailableScreenModeRotations0(dpy, screen_idx);
- if(null==nrotations || 0==nrotations.length) {
- return null;
- }
- nrotation_index = 0;
-
- nres_number = getNumScreenModeResolutions0(dpy, screen_idx);
- if(0==nres_number) {
- return null;
- }
- nres_index = 0;
-
- nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
- if(null==nrates || 0==nrates.length) {
- return null;
- }
- nrate_index = 0;
-
- nmode_number = 0;
-
- return getScreenModeNextImpl();
- } } );
- }
-
- protected int[] getScreenModeNextImpl() {
- // assemble: w x h x bpp x f x r
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<int[]>() {
- public int[] run(long dpy) {
- /**
- System.err.println("******** mode: "+nmode_number);
- System.err.println("rot "+nrotation_index);
- System.err.println("rate "+nrate_index);
- System.err.println("res "+nres_index); */
-
- int[] res = getScreenModeResolution0(dpy, screen_idx, nres_index);
- if(null==res || 0==res.length) {
- return null;
- }
- if(0>=res[0] || 0>=res[1]) {
- throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+nres_index+"/"+nres_number);
- }
- int rate = nrates[nrate_index];
- if(0>=rate) {
- rate = default_sm_rate;
- if(DEBUG) {
- System.err.println("Invalid rate: "+rate+" at index "+nrate_index+"/"+nrates.length+", using default: "+default_sm_rate);
- }
- }
- int rotation = nrotations[nrotation_index];
-
- int[] props = new int[ 1 + ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL ];
- int i = 0;
- props[i++] = nres_index; // use resolution index, not unique for native -> ScreenMode
- props[i++] = 0; // set later for verification of iterator
- props[i++] = res[0]; // width
- props[i++] = res[1]; // height
- props[i++] = default_sm_bpp; // FIXME
- props[i++] = res[2]; // widthmm
- props[i++] = res[3]; // heightmm
- props[i++] = rate; // rate
- props[i++] = rotation;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i - 1; // count without extra element
-
- nmode_number++;
-
- // iteration: r -> f -> bpp -> [w x h]
- nrotation_index++;
- if(nrotation_index == nrotations.length) {
- nrotation_index=0;
- nrate_index++;
- if(null == nrates || nrate_index == nrates.length){
- nres_index++;
- if(nres_index == nres_number) {
- // done
- nrates=null;
- nrotations=null;
- return null;
- }
-
- nrates = getScreenModeRates0(dpy, screen_idx, nres_index);
- if(null==nrates || 0==nrates.length) {
- return null;
- }
- nrate_index = 0;
- }
- }
-
- return props;
- } } );
- }
-
- protected ScreenMode getCurrentScreenModeImpl() {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<ScreenMode>() {
- public ScreenMode run(long dpy) {
- long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
- if(0 == screenConfigHandle) {
- return null;
- }
- int[] res;
- int rate, rot;
- try {
- int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
- if(0==resNumber) {
- return null;
- }
-
- int resIdx = getCurrentScreenResolutionIndex0(screenConfigHandle);
- if(0>resIdx) {
- return null;
- }
- if(resIdx>=resNumber) {
- throw new RuntimeException("Invalid resolution index: ! "+resIdx+" < "+resNumber);
- }
- res = getScreenModeResolution0(dpy, screen_idx, resIdx);
- if(null==res || 0==res.length) {
- return null;
- }
- if(0>=res[0] || 0>=res[1]) {
- throw new InternalError("invalid resolution: "+res[0]+"x"+res[1]+" for res idx "+resIdx+"/"+resNumber);
- }
- rate = getCurrentScreenRate0(screenConfigHandle);
- if(0>rate) {
- return null;
- }
- rot = getCurrentScreenRotation0(screenConfigHandle);
- if(0>rot) {
- return null;
- }
- } finally {
- freeScreenConfiguration0(screenConfigHandle);
- }
- int[] props = new int[ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL];
- int i = 0;
- props[i++] = 0; // set later for verification of iterator
- props[i++] = res[0]; // width
- props[i++] = res[1]; // height
- props[i++] = default_sm_bpp; // FIXME
- props[i++] = res[2]; // widthmm
- props[i++] = res[3]; // heightmm
- props[i++] = rate; // rate
- props[i++] = rot;
- props[i - ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL] = i; // count
- return ScreenModeUtil.streamIn(props, 0);
- } } );
- }
-
- protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) {
- final List<ScreenMode> screenModes = this.getScreenModesOrig();
- final int screenModeIdx = screenModes.indexOf(screenMode);
- if(0>screenModeIdx) {
- throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode);
- }
- final long t0 = System.currentTimeMillis();
- boolean done = runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- boolean done = false;
- long screenConfigHandle = getScreenConfiguration0(dpy, screen_idx);
- if(0 == screenConfigHandle) {
- return Boolean.valueOf(done);
- }
- try {
- int resNumber = getNumScreenModeResolutions0(dpy, screen_idx);
- int resIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx);
- if(0>resIdx || resIdx>=resNumber) {
- throw new RuntimeException("Invalid resolution index: ! 0 < "+resIdx+" < "+resNumber+", screenMode["+screenModeIdx+"] "+screenMode);
- }
-
- final int f = screenMode.getMonitorMode().getRefreshRate();
- final int r = screenMode.getRotation();
-
- if( setCurrentScreenModeStart0(dpy, screen_idx, screenConfigHandle, resIdx, f, r) ) {
- while(!done && System.currentTimeMillis()-t0 < SCREEN_MODE_CHANGE_TIMEOUT) {
- done = setCurrentScreenModePollEnd0(dpy, screen_idx, resIdx, f, r);
- if(!done) {
- try { Thread.sleep(10); } catch (InterruptedException e) { }
- }
- }
- }
- } finally {
- freeScreenConfiguration0(screenConfigHandle);
- }
- return Boolean.valueOf(done);
- }
- }).booleanValue();
-
- if(DEBUG || !done) {
- System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+
- (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode);
- }
- return done;
- }
-
- private class XineramaEnabledQuery implements DisplayImpl.DisplayRunnable<Boolean> {
- public Boolean run(long dpy) {
- return new Boolean(X11Util.XineramaIsEnabled(dpy));
- }
- }
- private XineramaEnabledQuery xineramaEnabledQuery = new XineramaEnabledQuery();
-
- protected int validateScreenIndex(final int idx) {
- if(getDisplay().isNativeValid()) {
- return runWithLockedDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx;
- } else {
- return runWithTempDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx;
- }
- }
-
- protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) {
- display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- virtualOrigin.setX(0);
- virtualOrigin.setY(0);
- virtualSize.setWidth(getWidth0(dpy, screen_idx));
- virtualSize.setHeight(getHeight0(dpy, screen_idx));
- return null;
- } } );
- }
-
- //----------------------------------------------------------------------
- // Internals only
- //
- private final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- return display.runWithLockedDisplayHandle(action);
- // return runWithTempDisplayHandle(action);
- // return runWithoutLock(action);
- }
-
- private final <T> T runWithTempDisplayHandle(DisplayRunnable<T> action) {
- final long displayHandle = X11Util.openDisplay(display.getName());
- if(0 == displayHandle) {
- throw new RuntimeException("null device");
- }
- T res;
- try {
- res = action.run(displayHandle);
- } finally {
- X11Util.closeDisplay(displayHandle);
- }
- return res;
- }
- private final <T> T runWithoutLock(DisplayRunnable<T> action) {
- return action.run(display.getHandle());
- }
-
- private static native long GetScreen0(long dpy, int scrn_idx);
-
- private static native int getWidth0(long display, int scrn_idx);
-
- private static native int getHeight0(long display, int scrn_idx);
-
- /** @return int[] { rot1, .. } */
- private static native int[] getAvailableScreenModeRotations0(long display, int screen_index);
-
- private static native int getNumScreenModeResolutions0(long display, int screen_index);
-
- /** @return int[] { width, height, widthmm, heightmm } */
- private static native int[] getScreenModeResolution0(long display, int screen_index, int mode_index);
-
- private static native int[] getScreenModeRates0(long display, int screen_index, int mode_index);
-
- private static native long getScreenConfiguration0(long display, int screen_index);
- private static native void freeScreenConfiguration0(long screenConfiguration);
-
- private static native int getCurrentScreenResolutionIndex0(long screenConfiguration);
- private static native int getCurrentScreenRate0(long screenConfiguration);
- private static native int getCurrentScreenRotation0(long screenConfiguration);
-
- /** needs own Display connection for XRANDR event handling */
- private static native boolean setCurrentScreenModeStart0(long display, int screen_index, long screenConfiguration, int mode_index, int freq, int rot);
- private static native boolean setCurrentScreenModePollEnd0(long display, int screen_index, int mode_index, int freq, int rot);
-}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
deleted file mode 100644
index 143b94a57..000000000
--- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 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:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package jogamp.newt.driver.x11;
-
-import jogamp.nativewindow.x11.X11Lib;
-import jogamp.newt.DisplayImpl;
-import jogamp.newt.DisplayImpl.DisplayRunnable;
-import jogamp.newt.WindowImpl;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.nativewindow.util.Insets;
-import javax.media.nativewindow.util.InsetsImmutable;
-import javax.media.nativewindow.util.Point;
-
-import com.jogamp.newt.event.MouseEvent;
-
-public class X11Window extends WindowImpl {
- private static final String WINDOW_CLASS_NAME = "NewtWindow";
- private static final int X11_WHEEL_ONE_UP_BUTTON = 4;
- private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5;
- private static final int X11_WHEEL_TWO_UP_BUTTON = 6;
- private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7;
-
- static {
- X11Display.initSingleton();
- }
-
- public X11Window() {
- }
-
- protected void createNativeImpl() {
- final X11Screen screen = (X11Screen) getScreen();
- final X11Display display = (X11Display) screen.getDisplay();
- final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice());
- final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
- capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen());
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg);
- }
- if (null == cfg) {
- throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
- }
- final int visualID = cfg.getVisualID(VIDType.NATIVE);
- if(VisualIDHolder.VID_UNDEFINED == visualID) {
- throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg);
- }
- setGraphicsConfiguration(cfg);
- final int flags = getReconfigureFlags(0, true) &
- ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
- setWindowHandle(CreateWindow0(getParentWindowHandle(),
- display.getEDTHandle(), screen.getIndex(), visualID,
- display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
- getX(), getY(), getWidth(), getHeight(), autoPosition(), flags));
- windowHandleClose = getWindowHandle();
- if (0 == windowHandleClose) {
- throw new NativeWindowException("Error creating window");
- }
- }
-
- protected void closeNativeImpl() {
- if(0!=windowHandleClose && null!=getScreen() ) {
- X11Display display = (X11Display) getScreen().getDisplay();
- try {
- CloseWindow0(display.getEDTHandle(), windowHandleClose,
- display.getJavaObjectAtom(), display.getWindowDeleteAtom());
- } catch (Throwable t) {
- if(DEBUG_IMPLEMENTATION) {
- Exception e = new Exception("Warning: closeNativeImpl failed - "+Thread.currentThread().getName(), t);
- e.printStackTrace();
- }
- } finally {
- windowHandleClose = 0;
- }
- }
- }
-
- protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
- getReconfigureFlagsAsString(null, flags));
- }
- if(0 == ( FLAG_IS_UNDECORATED & flags)) {
- final InsetsImmutable i = getInsets();
-
- // client position -> top-level window position
- x -= i.getLeftWidth() ;
- y -= i.getTopHeight() ;
- }
- final X11Display display = (X11Display) getScreen().getDisplay();
- reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(),
- getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
- x, y, width, height, flags);
-
- return true;
- }
-
- protected void reparentNotify(long newParentWindowHandle) {
- if(DEBUG_IMPLEMENTATION) {
- final long p0 = getParentWindowHandle();
- System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle));
- }
- }
-
- protected void requestFocusImpl(boolean force) {
- requestFocus0(getDisplayEDTHandle(), getWindowHandle(), force);
- }
-
- @Override
- protected void setTitleImpl(final String title) {
- runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- setTitle0(dpy, getWindowHandle(), title);
- return null;
- }
- });
- }
-
- @Override
- protected boolean setPointerVisibleImpl(final boolean pointerVisible) {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- return Boolean.valueOf(setPointerVisible0(getDisplayEDTHandle(), getWindowHandle(), pointerVisible));
- }
- }).booleanValue();
- }
-
- @Override
- protected boolean confinePointerImpl(final boolean confine) {
- return runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
- public Boolean run(long dpy) {
- return Boolean.valueOf(confinePointer0(getDisplayEDTHandle(), getWindowHandle(), confine));
- }
- }).booleanValue();
- }
-
- @Override
- protected void warpPointerImpl(final int x, final int y) {
- runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- warpPointer0(getDisplayEDTHandle(), getWindowHandle(), x, y);
- return null;
- }
- });
- }
-
- protected Point getLocationOnScreenImpl(final int x, final int y) {
- // X11Util.GetRelativeLocation: locks display already !
- return X11Lib.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
- }
-
- protected void updateInsetsImpl(Insets insets) {
- // nop - using event driven insetsChange(..)
- }
-
- protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers,
- int x, int y, int button, int rotation) {
- switch(eventType) {
- case MouseEvent.EVENT_MOUSE_PRESSED:
- switch(button) {
- case X11_WHEEL_ONE_UP_BUTTON:
- case X11_WHEEL_ONE_DOWN_BUTTON:
- case X11_WHEEL_TWO_UP_BUTTON:
- case X11_WHEEL_TWO_DOWN_BUTTON:
- // ignore wheel pressed !
- return;
- }
- break;
- case MouseEvent.EVENT_MOUSE_RELEASED:
- switch(button) {
- case X11_WHEEL_ONE_UP_BUTTON:
- eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 1;
- rotation = 1;
- break;
- case X11_WHEEL_ONE_DOWN_BUTTON:
- eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 1;
- rotation = -1;
- break;
- case X11_WHEEL_TWO_UP_BUTTON:
- eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 2;
- rotation = 1;
- break;
- case X11_WHEEL_TWO_DOWN_BUTTON:
- eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
- button = 2;
- rotation = -1;
- break;
- }
- break;
- }
- super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation);
- }
-
-
- //----------------------------------------------------------------------
- // Internals only
- //
-
- private final long getDisplayEDTHandle() {
- return ((X11Display) getScreen().getDisplay()).getEDTHandle();
- }
- private final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) {
- return ((DisplayImpl) getScreen().getDisplay()).runWithLockedDisplayHandle(action);
- // return runWithTempDisplayHandle(action);
- }
-
- protected static native boolean initIDs0();
-
- 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);
- private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom);
- 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 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);
- private static native void warpPointer0(long display, long windowHandle, int x, int y);
-
- private long windowHandleClose;
-}
diff --git a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
index fae6560b4..38a434279 100644
--- a/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
+++ b/src/newt/classes/jogamp/newt/event/NEWTEventTask.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,12 +20,12 @@
* 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.event;
import com.jogamp.newt.event.NEWTEvent;
@@ -35,17 +35,22 @@ import com.jogamp.newt.event.NEWTEvent;
* which notifies after sending the event for the <code>invokeAndWait()</code> semantics.
*/
public class NEWTEventTask {
- NEWTEvent event;
- Object notifyObject;
+ private NEWTEvent event;
+ private Object notifyObject;
+ private RuntimeException exception;
public NEWTEventTask(NEWTEvent event, Object notifyObject) {
this.event = event ;
this.notifyObject = notifyObject ;
+ this.exception = null;
}
- public NEWTEvent get() { return event; }
+ public final NEWTEvent get() { return event; }
+ public final void setException(RuntimeException e) { exception = e; }
+ public final RuntimeException getException() { return exception; }
+ public final boolean isCallerWaiting() { return null != notifyObject; }
- public void notifyIssuer() {
+ public void notifyCaller() {
if(null != notifyObject) {
synchronized (notifyObject) {
notifyObject.notifyAll();
diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
new file mode 100644
index 000000000..db89690f4
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
@@ -0,0 +1,364 @@
+/**
+ * Copyright 2012 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.swt;
+
+import javax.media.nativewindow.NativeWindowException;
+
+import jogamp.newt.Debug;
+
+import com.jogamp.common.util.RunnableTask;
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * Simple {@link EDTUtil} implementation utilizing the SWT UI thread
+ * of the given {@link Display}.
+ */
+public class SWTEDTUtil implements EDTUtil {
+ public static final boolean DEBUG = Debug.debug("EDT");
+
+ private final Object edtLock = new Object(); // locking the EDT start/stop state
+ private final ThreadGroup threadGroup;
+ private final String name;
+ private final Runnable dispatchMessages;
+ private final org.eclipse.swt.widgets.Display swtDisplay;
+ private NEDT nedt = null;
+ private int start_iter=0;
+ private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
+
+ public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) {
+ this.threadGroup = Thread.currentThread().getThreadGroup();
+ this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-";
+ this.dispatchMessages = new Runnable() {
+ @Override
+ public void run() {
+ ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
+ } };
+ this.swtDisplay = swtDisplay;
+ this.nedt = new NEDT(threadGroup, name);
+ this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+
+ public final org.eclipse.swt.widgets.Display getDisplay() {
+ return swtDisplay;
+ }
+
+ @Override
+ public long getPollPeriod() {
+ return pollPeriod;
+ }
+
+ @Override
+ public void setPollPeriod(long ms) {
+ pollPeriod = ms;
+ }
+
+ @Override
+ public final boolean start() throws IllegalStateException {
+ final boolean swtDisposed = swtDisplay.isDisposed();
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ final Thread curT = Thread.currentThread();
+ final Thread swtT = !swtDisposed ? swtDisplay.getThread() : null;
+ final boolean onSWTEDT = swtT == curT;
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+curT.getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", SWT-EDT "+swtT.getName()+", on SWT-EDT "+onSWTEDT);
+ }
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt+", swtDisposed (skipping) "+swtDisposed);
+ }
+ if( !swtDisposed ) {
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
+ }
+ }
+ if( !swtDisposed ) {
+ return invoke(true, nullTask);
+ } else {
+ return false;
+ }
+ }
+
+ private final void startImpl() {
+ if(nedt.isAlive()) {
+ throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
+ }
+ start_iter++;
+ nedt.setName(name+start_iter);
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
+ // Thread.dumpStack();
+ }
+ nedt.start();
+ }
+
+ @Override
+ public boolean isCurrentThreadEDT() {
+ return !swtDisplay.isDisposed() && swtDisplay.getThread() == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadNEDT() {
+ return nedt == Thread.currentThread();
+ }
+
+ @Override
+ public final boolean isCurrentThreadEDTorNEDT() {
+ final Thread ct = Thread.currentThread();
+ return ( !swtDisplay.isDisposed() && ct == swtDisplay.getThread() ) || ct == nedt ;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return nedt.isRunning();
+ }
+
+ @Override
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, true);
+ }
+
+ @Override
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false);
+ }
+
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) {
+ Throwable throwable = null;
+ RunnableTask rTask = null;
+ final Object rTaskLock = new Object();
+ synchronized(rTaskLock) { // lock the optional task execution
+ synchronized(edtLock) { // lock the EDT status
+ if( nedt.shouldStop ) {
+ // drop task ..
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ if( swtDisplay.isDisposed() ) {
+ stop = true;
+ }
+
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if( stop ) {
+ nedt.shouldStop = true;
+ }
+ } else {
+ if( !nedt.isRunning && !swtDisplay.isDisposed() ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if( nedt.isRunning ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+ if( swtDisplay.isDisposed() ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. "+nedt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ }
+
+ if( null != task ) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ swtDisplay.asyncExec(rTask);
+ }
+ }
+ }
+ if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ if(throwable instanceof NativeWindowException) {
+ throw (NativeWindowException)throwable;
+ }
+ throw new RuntimeException(throwable);
+ }
+ }
+ return true;
+ }
+ }
+
+ @Override
+ final public boolean waitUntilIdle() {
+ final NEDT _nedt;
+ synchronized(edtLock) {
+ _nedt = nedt;
+ }
+ final Thread ct = Thread.currentThread();
+ if( !_nedt.isRunning || _nedt == ct || swtDisplay.isDisposed() || swtDisplay.getThread() == ct ) {
+ return false;
+ }
+ try {
+ swtDisplay.syncExec(new Runnable() {
+ @Override
+ public void run() { }
+ });
+ } catch (Exception e) { }
+ return true;
+ }
+
+ @Override
+ final public boolean waitUntilStopped() {
+ synchronized(edtLock) {
+ final Thread curT = Thread.currentThread();
+ final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null;
+ final boolean onSWTEDT = swtT == curT;
+ if( nedt.isRunning && nedt != curT && !onSWTEDT ) {
+ while( nedt.isRunning ) {
+ try {
+ edtLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ class NEDT extends Thread {
+ volatile boolean shouldStop = false;
+ volatile boolean isRunning = false;
+ Object sync = new Object();
+
+ public NEDT(ThreadGroup tg, String name) {
+ super(tg, name);
+ }
+
+ final public boolean isRunning() {
+ return isRunning && !shouldStop;
+ }
+
+ @Override
+ final public void start() throws IllegalThreadStateException {
+ isRunning = true;
+ super.start();
+ }
+
+ /**
+ * Utilizing locking only on tasks and its execution,
+ * not for event dispatching.
+ */
+ @Override
+ final public void run() {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() START "+ getName());
+ }
+ RuntimeException error = null;
+ try {
+ do {
+ // event dispatch
+ if(!shouldStop) {
+ // EDT invoke thread is SWT-EDT,
+ // hence dispatching is required to run on SWT-EDT as well.
+ // Otherwise a deadlock may happen due to dispatched event's
+ // triggering a locking action.
+ if ( !swtDisplay.isDisposed() ) {
+ swtDisplay.syncExec(dispatchMessages);
+ } else {
+ dispatchMessages.run();
+ }
+ }
+ // wait
+ synchronized(sync) {
+ if(!shouldStop) {
+ try {
+ sync.wait(pollPeriod);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ } while(!shouldStop) ;
+ } catch (Throwable t) {
+ // handle errors ..
+ shouldStop = true;
+ if(t instanceof RuntimeException) {
+ error = (RuntimeException) t;
+ } else {
+ error = new RuntimeException("Within SWT-EDT", t);
+ }
+ } finally {
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error);
+ }
+ synchronized(edtLock) {
+ isRunning = false;
+ edtLock.notifyAll();
+ }
+ if(DEBUG) {
+ System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
+ }
+ if(null!=error) {
+ throw error;
+ }
+ } // finally
+ } // run()
+ } // EventDispatchThread
+
+}
diff --git a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
new file mode 100644
index 000000000..b5c45c1aa
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
@@ -0,0 +1,375 @@
+/**
+ * Copyright 2012 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.swt.event;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.MouseEvent;
+
+/**
+ * SWT event translator to NEWT, inclusive dispatch listener.
+ * <p>
+ * <b>Disclaimer:</b> This code is merely tested and subject to change.
+ * </p>
+ */
+public class SWTNewtEventFactory {
+
+ public static final short eventTypeSWT2NEWT(int swtType) {
+ switch( swtType ) {
+ // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED;
+ case SWT.MouseDown: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_PRESSED;
+ case SWT.MouseUp: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_RELEASED;
+ case SWT.MouseMove: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_MOVED;
+ case SWT.MouseEnter: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_ENTERED;
+ case SWT.MouseExit: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_EXITED;
+ // case SWT.MouseXXX: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED;
+ case SWT.MouseVerticalWheel: return com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
+
+ case SWT.KeyDown: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
+ case SWT.KeyUp: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
+ }
+ return (short)0;
+ }
+
+ public static final int swtModifiers2Newt(int awtMods, boolean mouseHint) {
+ int newtMods = 0;
+ if ((awtMods & SWT.SHIFT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.SHIFT_MASK;
+ if ((awtMods & SWT.CTRL) != 0) newtMods |= com.jogamp.newt.event.InputEvent.CTRL_MASK;
+ if ((awtMods & SWT.ALT) != 0) newtMods |= com.jogamp.newt.event.InputEvent.ALT_MASK;
+ return newtMods;
+ }
+
+ public static short swtKeyCode2NewtKeyCode(final int swtKeyCode) {
+ final short defNEWTKeyCode = (short)swtKeyCode;
+ switch (swtKeyCode) {
+ case SWT.HOME : return com.jogamp.newt.event.KeyEvent.VK_HOME;
+ case SWT.END : return com.jogamp.newt.event.KeyEvent.VK_END;
+ case SWT.PRINT_SCREEN : return com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN;
+ case SWT.BS : return com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE;
+ case SWT.TAB : return com.jogamp.newt.event.KeyEvent.VK_TAB;
+ case SWT.LF : return com.jogamp.newt.event.KeyEvent.VK_ENTER;
+ case SWT.PAGE_DOWN : return com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN;
+ case SWT.PAGE_UP : return com.jogamp.newt.event.KeyEvent.VK_PAGE_UP;
+ case SWT.CONTROL : return com.jogamp.newt.event.KeyEvent.VK_CONTROL;
+ case SWT.CAPS_LOCK : return com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK;
+ case SWT.PAUSE : return com.jogamp.newt.event.KeyEvent.VK_PAUSE;
+ case SWT.SCROLL_LOCK : return com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK;
+ case SWT.CANCEL : return com.jogamp.newt.event.KeyEvent.VK_CANCEL;
+ case SWT.INSERT : return com.jogamp.newt.event.KeyEvent.VK_INSERT;
+ case SWT.ESC : return com.jogamp.newt.event.KeyEvent.VK_ESCAPE;
+ case SWT.SPACE : return com.jogamp.newt.event.KeyEvent.VK_SPACE;
+ case SWT.F1 : return com.jogamp.newt.event.KeyEvent.VK_F1;
+ case SWT.F2 : return com.jogamp.newt.event.KeyEvent.VK_F2;
+ case SWT.F3 : return com.jogamp.newt.event.KeyEvent.VK_F3;
+ case SWT.F4 : return com.jogamp.newt.event.KeyEvent.VK_F4;
+ case SWT.F5 : return com.jogamp.newt.event.KeyEvent.VK_F5;
+ case SWT.F6 : return com.jogamp.newt.event.KeyEvent.VK_F6;
+ case SWT.F7 : return com.jogamp.newt.event.KeyEvent.VK_F7;
+ case SWT.F8 : return com.jogamp.newt.event.KeyEvent.VK_F8;
+ case SWT.F9 : return com.jogamp.newt.event.KeyEvent.VK_F9;
+ case SWT.F10 : return com.jogamp.newt.event.KeyEvent.VK_F10;
+ case SWT.F11 : return com.jogamp.newt.event.KeyEvent.VK_F11;
+ case SWT.F12 : return com.jogamp.newt.event.KeyEvent.VK_F12;
+ case SWT.F13 : return com.jogamp.newt.event.KeyEvent.VK_F13;
+ case SWT.F14 : return com.jogamp.newt.event.KeyEvent.VK_F14;
+ case SWT.F15 : return com.jogamp.newt.event.KeyEvent.VK_F15;
+ case SWT.F16 : return com.jogamp.newt.event.KeyEvent.VK_F16;
+ case SWT.F17 : return com.jogamp.newt.event.KeyEvent.VK_F17;
+ case SWT.F18 : return com.jogamp.newt.event.KeyEvent.VK_F18;
+ case SWT.F19 : return com.jogamp.newt.event.KeyEvent.VK_F19;
+ case SWT.F20 : return com.jogamp.newt.event.KeyEvent.VK_F20;
+ case SWT.DEL : return com.jogamp.newt.event.KeyEvent.VK_DELETE;
+ case SWT.KEYPAD_0 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD0;
+ case SWT.KEYPAD_1 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD1;
+ case SWT.KEYPAD_2 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD2;
+ case SWT.KEYPAD_3 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD3;
+ case SWT.KEYPAD_4 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD4;
+ case SWT.KEYPAD_5 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD5;
+ case SWT.KEYPAD_6 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD6;
+ case SWT.KEYPAD_7 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD7;
+ case SWT.KEYPAD_8 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD8;
+ case SWT.KEYPAD_9 : return com.jogamp.newt.event.KeyEvent.VK_NUMPAD9;
+ case SWT.KEYPAD_DECIMAL: return com.jogamp.newt.event.KeyEvent.VK_DECIMAL;
+ case SWT.KEYPAD_ADD : return com.jogamp.newt.event.KeyEvent.VK_ADD;
+ case SWT.KEYPAD_SUBTRACT: return com.jogamp.newt.event.KeyEvent.VK_SUBTRACT;
+ case SWT.KEYPAD_MULTIPLY: return com.jogamp.newt.event.KeyEvent.VK_MULTIPLY;
+ case SWT.KEYPAD_DIVIDE : return com.jogamp.newt.event.KeyEvent.VK_DIVIDE;
+ case SWT.NUM_LOCK : return com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK;
+ case SWT.ARROW_LEFT : return com.jogamp.newt.event.KeyEvent.VK_LEFT;
+ case SWT.ARROW_UP : return com.jogamp.newt.event.KeyEvent.VK_UP;
+ case SWT.ARROW_RIGHT : return com.jogamp.newt.event.KeyEvent.VK_RIGHT;
+ case SWT.ARROW_DOWN : return com.jogamp.newt.event.KeyEvent.VK_DOWN;
+ case SWT.HELP : return com.jogamp.newt.event.KeyEvent.VK_HELP;
+ }
+ return defNEWTKeyCode;
+ }
+
+ public static int newtKeyCode2SWTKeyCode(final short newtKeyCode) {
+ final int defSWTKeyCode = 0xFFFF & (int)newtKeyCode;
+ switch (newtKeyCode) {
+ case com.jogamp.newt.event.KeyEvent.VK_HOME : return SWT.HOME;
+ case com.jogamp.newt.event.KeyEvent.VK_END : return SWT.END;
+ case com.jogamp.newt.event.KeyEvent.VK_PRINTSCREEN : return SWT.PRINT_SCREEN;
+ case com.jogamp.newt.event.KeyEvent.VK_BACK_SPACE : return SWT.BS;
+ case com.jogamp.newt.event.KeyEvent.VK_TAB : return SWT.TAB;
+ case com.jogamp.newt.event.KeyEvent.VK_ENTER : return SWT.LF;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_DOWN : return SWT.PAGE_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_PAGE_UP : return SWT.PAGE_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_CONTROL : return SWT.CONTROL;
+ case com.jogamp.newt.event.KeyEvent.VK_CAPS_LOCK : return SWT.CAPS_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_PAUSE : return SWT.PAUSE;
+ case com.jogamp.newt.event.KeyEvent.VK_SCROLL_LOCK : return SWT.SCROLL_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_CANCEL : return SWT.CANCEL;
+ case com.jogamp.newt.event.KeyEvent.VK_INSERT : return SWT.INSERT;
+ case com.jogamp.newt.event.KeyEvent.VK_ESCAPE : return SWT.ESC;
+ case com.jogamp.newt.event.KeyEvent.VK_SPACE : return SWT.SPACE;
+ case com.jogamp.newt.event.KeyEvent.VK_F1 : return SWT.F1;
+ case com.jogamp.newt.event.KeyEvent.VK_F2 : return SWT.F2;
+ case com.jogamp.newt.event.KeyEvent.VK_F3 : return SWT.F3;
+ case com.jogamp.newt.event.KeyEvent.VK_F4 : return SWT.F4;
+ case com.jogamp.newt.event.KeyEvent.VK_F5 : return SWT.F5;
+ case com.jogamp.newt.event.KeyEvent.VK_F6 : return SWT.F6;
+ case com.jogamp.newt.event.KeyEvent.VK_F7 : return SWT.F7;
+ case com.jogamp.newt.event.KeyEvent.VK_F8 : return SWT.F8;
+ case com.jogamp.newt.event.KeyEvent.VK_F9 : return SWT.F9;
+ case com.jogamp.newt.event.KeyEvent.VK_F10 : return SWT.F10;
+ case com.jogamp.newt.event.KeyEvent.VK_F11 : return SWT.F11;
+ case com.jogamp.newt.event.KeyEvent.VK_F12 : return SWT.F12;
+ case com.jogamp.newt.event.KeyEvent.VK_F13 : return SWT.F13;
+ case com.jogamp.newt.event.KeyEvent.VK_F14 : return SWT.F14;
+ case com.jogamp.newt.event.KeyEvent.VK_F15 : return SWT.F15;
+ case com.jogamp.newt.event.KeyEvent.VK_F16 : return SWT.F16;
+ case com.jogamp.newt.event.KeyEvent.VK_F17 : return SWT.F17;
+ case com.jogamp.newt.event.KeyEvent.VK_F18 : return SWT.F18;
+ case com.jogamp.newt.event.KeyEvent.VK_F19 : return SWT.F19;
+ case com.jogamp.newt.event.KeyEvent.VK_F20 : return SWT.F20;
+ case com.jogamp.newt.event.KeyEvent.VK_DELETE : return SWT.DEL;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD0 : return SWT.KEYPAD_0;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD1 : return SWT.KEYPAD_1;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD2 : return SWT.KEYPAD_2;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD3 : return SWT.KEYPAD_3;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD4 : return SWT.KEYPAD_4;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD5 : return SWT.KEYPAD_5;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD6 : return SWT.KEYPAD_6;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD7 : return SWT.KEYPAD_7;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD8 : return SWT.KEYPAD_8;
+ case com.jogamp.newt.event.KeyEvent.VK_NUMPAD9 : return SWT.KEYPAD_9;
+ case com.jogamp.newt.event.KeyEvent.VK_DECIMAL : return SWT.KEYPAD_DECIMAL;
+ case com.jogamp.newt.event.KeyEvent.VK_ADD : return SWT.KEYPAD_ADD;
+ case com.jogamp.newt.event.KeyEvent.VK_SUBTRACT : return SWT.KEYPAD_SUBTRACT;
+ case com.jogamp.newt.event.KeyEvent.VK_MULTIPLY : return SWT.KEYPAD_MULTIPLY;
+ case com.jogamp.newt.event.KeyEvent.VK_DIVIDE : return SWT.KEYPAD_DIVIDE;
+ case com.jogamp.newt.event.KeyEvent.VK_NUM_LOCK : return SWT.NUM_LOCK;
+ case com.jogamp.newt.event.KeyEvent.VK_LEFT : return SWT.ARROW_LEFT;
+ case com.jogamp.newt.event.KeyEvent.VK_UP : return SWT.ARROW_UP;
+ case com.jogamp.newt.event.KeyEvent.VK_RIGHT : return SWT.ARROW_RIGHT;
+ case com.jogamp.newt.event.KeyEvent.VK_DOWN : return SWT.ARROW_DOWN;
+ case com.jogamp.newt.event.KeyEvent.VK_HELP : return SWT.HELP;
+ }
+ return defSWTKeyCode;
+ }
+
+
+ public static final com.jogamp.newt.event.InputEvent createInputEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ com.jogamp.newt.event.InputEvent res = createMouseEvent(event, source);
+ if(null == res) {
+ res = createKeyEvent(event, source);
+ }
+ return res;
+ }
+
+ public static final com.jogamp.newt.event.MouseEvent createMouseEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ case SWT.MouseUp:
+ case SWT.MouseMove:
+ case SWT.MouseEnter:
+ case SWT.MouseExit:
+ case SWT.MouseVerticalWheel:
+ break;
+ default:
+ return null;
+ }
+ final short type = eventTypeSWT2NEWT(event.type);
+ if( (short)0 != type ) {
+ float rotation = 0;
+ if (SWT.MouseVerticalWheel == event.type) {
+ // SWT/NEWT rotation is reversed - AWT +1 is down, NEWT +1 is up.
+ // rotation = -1 * (int) event.rotation;
+ rotation = (float) event.rotation;
+ }
+
+ int mods = swtModifiers2Newt(event.stateMask, true);
+
+ if( source instanceof com.jogamp.newt.Window) {
+ final com.jogamp.newt.Window newtSource = (com.jogamp.newt.Window)source;
+ if(newtSource.isPointerConfined()) {
+ mods |= InputEvent.CONFINED_MASK;
+ }
+ if(!newtSource.isPointerVisible()) {
+ mods |= InputEvent.INVISIBLE_MASK;
+ }
+ }
+
+ return new com.jogamp.newt.event.MouseEvent(
+ type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+ mods, event.x, event.y, (short)event.count, (short)event.button, MouseEvent.getRotationXYZ(rotation, mods), 1f);
+ }
+ return null; // no mapping ..
+ }
+
+ public static final com.jogamp.newt.event.KeyEvent createKeyEvent(org.eclipse.swt.widgets.Event event, Object source) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ case SWT.KeyUp:
+ break;
+ default:
+ return null;
+ }
+ final short type = eventTypeSWT2NEWT(event.type);
+ if( (short)0 != type ) {
+ final short newtKeyCode = swtKeyCode2NewtKeyCode( event.keyCode );
+ return com.jogamp.newt.event.KeyEvent.create(
+ type, (null==source)?(Object)event.data:source, (0xFFFFFFFFL & (long)event.time),
+ swtModifiers2Newt(event.stateMask, false),
+ newtKeyCode, newtKeyCode, event.character);
+ }
+ return null; // no mapping ..
+ }
+
+ //
+ //
+ //
+
+ short dragButtonDown = 0;
+
+ public SWTNewtEventFactory() {
+ resetButtonsDown();
+ }
+
+ final void resetButtonsDown() {
+ dragButtonDown = 0;
+ }
+
+ public final boolean dispatchMouseEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.MouseListener l) {
+ com.jogamp.newt.event.MouseEvent res = createMouseEvent(event, source);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.MouseDown:
+ dragButtonDown = (short) event.button;
+ l.mousePressed(res); break;
+ case SWT.MouseUp:
+ dragButtonDown = 0;
+ l.mouseReleased(res);
+ {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_CLICKED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ res.getButton(), res.getRotation(), res.getRotationScale());
+ l.mouseClicked(res2);
+ }
+ break;
+ case SWT.MouseMove:
+ if( 0 < dragButtonDown ) {
+ final com.jogamp.newt.event.MouseEvent res2 = new com.jogamp.newt.event.MouseEvent(
+ com.jogamp.newt.event.MouseEvent.EVENT_MOUSE_DRAGGED,
+ res.getSource(),
+ res.getWhen(), res.getModifiers(),
+ res.getX(), res.getY(), res.getClickCount(),
+ dragButtonDown, res.getRotation(), res.getRotationScale());
+ l.mouseDragged( res2 );
+ } else {
+ l.mouseMoved(res);
+ }
+ break;
+ case SWT.MouseEnter:
+ l.mouseEntered(res);
+ break;
+ case SWT.MouseExit:
+ resetButtonsDown();
+ l.mouseExited(res);
+ break;
+ case SWT.MouseVerticalWheel:
+ l.mouseWheelMoved(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final boolean dispatchKeyEvent(org.eclipse.swt.widgets.Event event, Object source, com.jogamp.newt.event.KeyListener l) {
+ com.jogamp.newt.event.KeyEvent res = createKeyEvent(event, source);
+ if(null != res) {
+ if(null != l) {
+ switch(event.type) {
+ case SWT.KeyDown:
+ l.keyPressed(res);
+ break;
+ case SWT.KeyUp:
+ l.keyReleased(res);
+ break;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public final void attachDispatchListener(final org.eclipse.swt.widgets.Control ctrl, final Object source,
+ final com.jogamp.newt.event.MouseListener ml,
+ final com.jogamp.newt.event.KeyListener kl) {
+ final Listener listener = new Listener () {
+ @Override
+ public void handleEvent (Event event) {
+ if( dispatchMouseEvent( event, source, ml ) ) {
+ return;
+ }
+ if( dispatchKeyEvent( event, source, kl ) ) {
+ return;
+ }
+ } };
+ ctrl.addListener(SWT.MouseDown, listener);
+ ctrl.addListener(SWT.MouseUp, listener);
+ ctrl.addListener(SWT.MouseMove, listener);
+ ctrl.addListener(SWT.MouseEnter, listener);
+ ctrl.addListener(SWT.MouseExit, listener);
+ ctrl.addListener(SWT.MouseVerticalWheel, listener);
+ ctrl.addListener(SWT.KeyDown, listener);
+ ctrl.addListener(SWT.KeyUp, listener);
+ }
+}
+
diff --git a/src/newt/native/AndroidWindow.c b/src/newt/native/AndroidWindow.c
index fa5765672..94695e1d3 100644
--- a/src/newt/native/AndroidWindow.c
+++ b/src/newt/native/AndroidWindow.c
@@ -9,7 +9,7 @@
#include <unistd.h>
#include <errno.h>
-#include "jogamp_newt_driver_android_AndroidWindow.h"
+#include "jogamp_newt_driver_android_WindowDriver.h"
#include <android/native_window.h>
#include <android/native_window_jni.h>
@@ -23,56 +23,56 @@
#endif
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getSurfaceHandle0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_android_WindowDriver_getSurfaceHandle0
(JNIEnv *env, jclass clazz, jobject surface)
{
ANativeWindow * anw = ANativeWindow_fromSurface(env, surface);
return (jlong) (intptr_t) anw;
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getSurfaceVisualID0
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getSurfaceVisualID0
(JNIEnv *env, jclass clazz, jlong surfaceHandle)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
return (jint) ANativeWindow_getFormat(anw);
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_setSurfaceVisualID0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_setSurfaceVisualID0
(JNIEnv *env, jclass clazz, jlong surfaceHandle, jint nativeVisualID)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
ANativeWindow_setBuffersGeometry(anw, 0, 0, nativeVisualID);
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getWidth0
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getWidth0
(JNIEnv *env, jclass clazz, jlong surfaceHandle)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
return (jint) ANativeWindow_getWidth(anw);
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_AndroidWindow_getHeight0
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_android_WindowDriver_getHeight0
(JNIEnv *env, jclass clazz, jlong surfaceHandle)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
return (jint) ANativeWindow_getHeight(anw);
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_acquire0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_acquire0
(JNIEnv *env, jclass clazz, jlong surfaceHandle)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
ANativeWindow_acquire(anw);
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_AndroidWindow_release0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_android_WindowDriver_release0
(JNIEnv *env, jclass clazz, jlong surfaceHandle)
{
ANativeWindow * anw = (ANativeWindow *) (intptr_t) surfaceHandle;
ANativeWindow_release(anw);
}
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_android_AndroidWindow_initIDs0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_android_WindowDriver_initIDs0
(JNIEnv *env, jclass clazz)
{
DBG_PRINT( "initIDs ok\n" );
diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h
index b42c06d21..2de46f82e 100644
--- a/src/newt/native/InputEvent.h
+++ b/src/newt/native/InputEvent.h
@@ -34,13 +34,30 @@
#ifndef _INPUT_EVENT_H_
#define _INPUT_EVENT_H_
-#define EVENT_SHIFT_MASK 1
-#define EVENT_CTRL_MASK 2
-#define EVENT_META_MASK 4
-#define EVENT_ALT_MASK 8
-#define EVENT_ALT_GRAPH_MASK 32
-#define EVENT_BUTTON1_MASK (1<<6)
-#define EVENT_BUTTON2_MASK (1<<7)
-#define EVENT_BUTTON3_MASK (1<<8)
+#define EVENT_SHIFT_MASK (1 << 0)
+#define EVENT_CTRL_MASK (1 << 1)
+#define EVENT_META_MASK (1 << 2)
+#define EVENT_ALT_MASK (1 << 3)
+#define EVENT_ALT_GRAPH_MASK (1 << 4)
+
+#define EVENT_BUTTON1_MASK (1 << 5)
+#define EVENT_BUTTON2_MASK (1 << 6)
+#define EVENT_BUTTON3_MASK (1 << 7)
+#define EVENT_BUTTON4_MASK (1 << 8)
+#define EVENT_BUTTON5_MASK (1 << 9)
+#define EVENT_BUTTON6_MASK (1 << 10)
+#define EVENT_BUTTON7_MASK (1 << 11)
+#define EVENT_BUTTON8_MASK (1 << 12)
+#define EVENT_BUTTON9_MASK (1 << 13)
+
+/** 16 buttons */
+#define EVENT_BUTTONLAST_MASK (1 << 20)
+
+/** 16 buttons */
+#define EVENT_BUTTONALL_MASK ( 0xffff << 5 )
+
+#define EVENT_AUTOREPEAT_MASK (1 << 29)
+#define EVENT_CONFINED_MASK (1 << 30)
+#define EVENT_INVISIBLE_MASK (1 << 31)
#endif
diff --git a/src/newt/native/IntelGDL.c b/src/newt/native/IntelGDL.c
index 690e1123d..a3bf101c5 100644
--- a/src/newt/native/IntelGDL.c
+++ b/src/newt/native/IntelGDL.c
@@ -37,9 +37,9 @@
#include <stdio.h>
#include <string.h>
-#include "jogamp_newt_driver_intel_gdl_Display.h"
-#include "jogamp_newt_driver_intel_gdl_Screen.h"
-#include "jogamp_newt_driver_intel_gdl_Window.h"
+#include "jogamp_newt_driver_intel_gdl_DisplayDriver.h"
+#include "jogamp_newt_driver_intel_gdl_ScreenDriver.h"
+#include "jogamp_newt_driver_intel_gdl_WindowDriver.h"
#include "MouseEvent.h"
#include "KeyEvent.h"
@@ -122,7 +122,7 @@ static void JNI_ThrowNew(JNIEnv *env, const char *throwable, const char* message
* Display
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DispatchMessages
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_DispatchMessages
(JNIEnv *env, jobject obj, jlong displayHandle, jobject focusedWindow)
{
// FIXME: n/a
@@ -137,7 +137,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DispatchMessage
} */
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Display_CreateDisplay
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_CreateDisplay
(JNIEnv *env, jobject obj)
{
gdl_ret_t retval;
@@ -170,7 +170,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Display_CreateDisplay
return (jlong) (intptr_t) p_driver_info;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DestroyDisplay
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_DisplayDriver_DestroyDisplay
(JNIEnv *env, jobject obj, jlong displayHandle)
{
gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
@@ -189,7 +189,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Display_DestroyDisplay
* Screen
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_initIDs
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_ScreenDriver_initIDs
(JNIEnv *env, jclass clazz)
{
screenCreatedID = (*env)->GetMethodID(env, clazz, "screenCreated", "(II)V");
@@ -201,7 +201,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_initIDs
return JNI_TRUE;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_GetScreenInfo
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_ScreenDriver_GetScreenInfo
(JNIEnv *env, jobject obj, jlong displayHandle, jint idx)
{
gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
@@ -233,7 +233,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Screen_GetScreenInfo
* Window
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Window_initIDs
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_initIDs
(JNIEnv *env, jclass clazz)
{
updateBoundsID = (*env)->GetMethodID(env, clazz, "updateBounds", "(IIII)V");
@@ -245,7 +245,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_intel_gdl_Window_initIDs
return JNI_TRUE;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CreateSurface
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_CreateSurface
(JNIEnv *env, jobject obj, jlong displayHandle, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) {
gdl_driver_info_t * p_driver_info = (gdl_driver_info_t *) (intptr_t) displayHandle;
@@ -338,7 +338,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CreateSurface
return (jlong) (intptr_t) plane;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CloseSurface
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_CloseSurface
(JNIEnv *env, jobject obj, jlong display, jlong surface)
{
gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ;
@@ -347,7 +347,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_CloseSurface
DBG_PRINT("[CloseSurface] plane %d\n", plane);
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_Window_SetBounds0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_intel_gdl_WindowDriver_SetBounds0
(JNIEnv *env, jobject obj, jlong surface, jint scr_width, jint scr_height, jint x, jint y, jint width, jint height) {
gdl_plane_id_t plane = (gdl_plane_id_t) (intptr_t) surface ;
diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c
index dc999138c..cfec60dc1 100644
--- a/src/newt/native/KDWindow.c
+++ b/src/newt/native/KDWindow.c
@@ -42,8 +42,9 @@
#include <gluegen_stdint.h>
#include <KD/kd.h>
+#include <EGL/egl.h>
-#include "jogamp_newt_driver_kd_KDWindow.h"
+#include "jogamp_newt_driver_kd_WindowDriver.h"
#include "MouseEvent.h"
#include "KeyEvent.h"
@@ -81,7 +82,7 @@ static jmethodID sendKeyEventID = NULL;
* Display
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDDisplay_DispatchMessages
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages
(JNIEnv *env, jobject obj)
{
const KDEvent * evt;
@@ -160,14 +161,14 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDDisplay_DispatchMessages
if(KD_INPUT_POINTER_SELECT==ptr->index) {
DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y);
(*env)->CallVoidMethod(env, javaWindow, sendMouseEventID,
- (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED,
+ (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED,
(jint) 0,
- (jint) ptr->x, (jint) ptr->y, 1, 0);
+ (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f);
} else {
DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y);
- (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
0,
- (jint) ptr->x, (jint) ptr->y, 0, 0);
+ (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f);
}
}
break;
@@ -179,7 +180,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDDisplay_DispatchMessages
* Window
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_KDWindow_initIDs
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs
(JNIEnv *env, jclass clazz)
{
#ifdef VERBOSE_ON
@@ -192,8 +193,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_KDWindow_initIDs
sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
if (windowCreatedID == NULL ||
sizeChangedID == NULL ||
visibleChangedID == NULL ||
@@ -207,12 +208,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_KDWindow_initIDs
return JNI_TRUE;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_CreateWindow
- (JNIEnv *env, jobject obj, jlong display, jintArray jAttrs)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_WindowDriver_CreateWindow
+ (JNIEnv *env, jobject obj, jlong display, jlong jeglConfig)
{
- jint * attrs = NULL;
- jsize attrsLen;
EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
+ EGLConfig eglConfig = (EGLConfig)(intptr_t)jeglConfig;
KDWindow *window = 0;
if(dpy==NULL) {
@@ -220,22 +220,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_CreateWindow
return 0;
}
- attrsLen = (*env)->GetArrayLength(env, jAttrs);
- if(0==attrsLen) {
- fprintf(stderr, "[CreateWindow] attribute array size 0..\n");
- return 0;
- }
- attrs = (*env)->GetIntArrayElements(env, jAttrs, 0);
- if(NULL==attrs) {
- fprintf(stderr, "[CreateWindow] attribute array NULL..\n");
- return 0;
- }
-
JOGLKDUserdata * userData = kdMalloc(sizeof(JOGLKDUserdata));
userData->magic = JOGL_KD_USERDATA_MAGIC;
- window = kdCreateWindow(dpy, attrs, (void *)userData);
-
- (*env)->ReleaseIntArrayElements(env, jAttrs, attrs, 0);
+ window = kdCreateWindow(dpy, eglConfig, (void *)userData);
if(NULL==window) {
kdFree(userData);
@@ -249,7 +236,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_CreateWindow
return (jlong) (intptr_t) window;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_RealizeWindow
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_WindowDriver_RealizeWindow
(JNIEnv *env, jobject obj, jlong window)
{
KDWindow *w = (KDWindow*) (intptr_t) window;
@@ -264,7 +251,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_RealizeWindow
return (jlong) (intptr_t) nativeWindow;
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_KDWindow_CloseWindow
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_WindowDriver_CloseWindow
(JNIEnv *env, jobject obj, jlong window, jlong juserData)
{
KDWindow *w = (KDWindow*) (intptr_t) window;
@@ -278,11 +265,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_kd_KDWindow_CloseWindow
}
/*
- * Class: jogamp_newt_driver_kd_KDWindow
+ * Class: jogamp_newt_driver_kd_WindowDriver
* Method: setVisible0
* Signature: (JJZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDWindow_setVisible0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setVisible0
(JNIEnv *env, jobject obj, jlong window, jboolean visible)
{
KDWindow *w = (KDWindow*) (intptr_t) window;
@@ -292,7 +279,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDWindow_setVisible0
(*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_FALSE, visible); // FIXME: or defer=true ?
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDWindow_setFullScreen0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setFullScreen0
(JNIEnv *env, jobject obj, jlong window, jboolean fullscreen)
{
/** not supported, due to missing NV property ..
@@ -309,7 +296,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDWindow_setFullScreen0
(void)fullscreen;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_KDWindow_setSize0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setSize0
(JNIEnv *env, jobject obj, jlong window, jint width, jint height)
{
KDWindow *w = (KDWindow*) (intptr_t) window;
diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h
index 0f7b1606b..c0a366a17 100644
--- a/src/newt/native/KeyEvent.h
+++ b/src/newt/native/KeyEvent.h
@@ -31,197 +31,203 @@
#define EVENT_KEY_PRESSED 300
#define EVENT_KEY_RELEASED 301
-#define EVENT_KEY_TYPED 302
-
-#define J_CHAR_UNDEFINED 0xFFFF;
-#define J_VK_ENTER '\n'
-#define J_VK_BACK_SPACE '\b'
-#define J_VK_TAB '\t'
-#define J_VK_CANCEL 0x03
-#define J_VK_CLEAR 0x0C
-#define J_VK_SHIFT 0x10
-#define J_VK_CONTROL 0x11
-#define J_VK_ALT 0x12
-#define J_VK_PAUSE 0x13
-#define J_VK_CAPS_LOCK 0x14
-#define J_VK_ESCAPE 0x1B
-#define J_VK_SPACE 0x20
-#define J_VK_PAGE_UP 0x21
-#define J_VK_PAGE_DOWN 0x22
-#define J_VK_END 0x23
-#define J_VK_HOME 0x24
-#define J_VK_LEFT 0x25
-#define J_VK_UP 0x26
-#define J_VK_RIGHT 0x27
-#define J_VK_DOWN 0x28
-#define J_VK_COMMA 0x2C
-#define J_VK_MINUS 0x2D
-#define J_VK_PERIOD 0x2E
-#define J_VK_SLASH 0x2F
-#define J_VK_0 0x30
-#define J_VK_1 0x31
-#define J_VK_2 0x32
-#define J_VK_3 0x33
-#define J_VK_4 0x34
-#define J_VK_5 0x35
-#define J_VK_6 0x36
-#define J_VK_7 0x37
-#define J_VK_8 0x38
-#define J_VK_9 0x39
-#define J_VK_SEMICOLON 0x3B
-#define J_VK_EQUALS 0x3D
-#define J_VK_A 0x41
-#define J_VK_B 0x42
-#define J_VK_C 0x43
-#define J_VK_D 0x44
-#define J_VK_E 0x45
-#define J_VK_F 0x46
-#define J_VK_G 0x47
-#define J_VK_H 0x48
-#define J_VK_I 0x49
-#define J_VK_J 0x4A
-#define J_VK_K 0x4B
-#define J_VK_L 0x4C
-#define J_VK_M 0x4D
-#define J_VK_N 0x4E
-#define J_VK_O 0x4F
-#define J_VK_P 0x50
-#define J_VK_Q 0x51
-#define J_VK_R 0x52
-#define J_VK_S 0x53
-#define J_VK_T 0x54
-#define J_VK_U 0x55
-#define J_VK_V 0x56
-#define J_VK_W 0x57
-#define J_VK_X 0x58
-#define J_VK_Y 0x59
-#define J_VK_Z 0x5A
-#define J_VK_OPEN_BRACKET 0x5B
-#define J_VK_BACK_SLASH 0x5C
-#define J_VK_CLOSE_BRACKET 0x5D
-#define J_VK_NUMPAD0 0x60
-#define J_VK_NUMPAD1 0x61
-#define J_VK_NUMPAD2 0x62
-#define J_VK_NUMPAD3 0x63
-#define J_VK_NUMPAD4 0x64
-#define J_VK_NUMPAD5 0x65
-#define J_VK_NUMPAD6 0x66
-#define J_VK_NUMPAD7 0x67
-#define J_VK_NUMPAD8 0x68
-#define J_VK_NUMPAD9 0x69
-#define J_VK_MULTIPLY 0x6A
-#define J_VK_ADD 0x6B
-#define J_VK_SEPARATOR 0x6C
-#define J_VK_SUBTRACT 0x6D
-#define J_VK_DECIMAL 0x6E
-#define J_VK_DIVIDE 0x6F
-#define J_VK_DELETE 0x7F /* ASCII DEL */
-#define J_VK_NUM_LOCK 0x90
-#define J_VK_SCROLL_LOCK 0x91
-#define J_VK_F1 0x70
-#define J_VK_F2 0x71
-#define J_VK_F3 0x72
-#define J_VK_F4 0x73
-#define J_VK_F5 0x74
-#define J_VK_F6 0x75
-#define J_VK_F7 0x76
-#define J_VK_F8 0x77
-#define J_VK_F9 0x78
-#define J_VK_F10 0x79
-#define J_VK_F11 0x7A
-#define J_VK_F12 0x7B
-#define J_VK_F13 0xF000
-#define J_VK_F14 0xF001
-#define J_VK_F15 0xF002
-#define J_VK_F16 0xF003
-#define J_VK_F17 0xF004
-#define J_VK_F18 0xF005
-#define J_VK_F19 0xF006
-#define J_VK_F20 0xF007
-#define J_VK_F21 0xF008
-#define J_VK_F22 0xF009
-#define J_VK_F23 0xF00A
-#define J_VK_F24 0xF00B
-#define J_VK_PRINTSCREEN 0x9A
-#define J_VK_INSERT 0x9B
-#define J_VK_HELP 0x9C
-#define J_VK_META 0x9D
-#define J_VK_BACK_QUOTE 0xC0
-#define J_VK_QUOTE 0xDE
-#define J_VK_KP_UP 0xE0
-#define J_VK_KP_DOWN 0xE1
-#define J_VK_KP_LEFT 0xE2
-#define J_VK_KP_RIGHT 0xE3
-#define J_VK_DEAD_GRAVE 0x80
-#define J_VK_DEAD_ACUTE 0x81
-#define J_VK_DEAD_CIRCUMFLEX 0x82
-#define J_VK_DEAD_TILDE 0x83
-#define J_VK_DEAD_MACRON 0x84
-#define J_VK_DEAD_BREVE 0x85
-#define J_VK_DEAD_ABOVEDOT 0x86
-#define J_VK_DEAD_DIAERESIS 0x87
-#define J_VK_DEAD_ABOVERING 0x88
-#define J_VK_DEAD_DOUBLEACUTE 0x89
-#define J_VK_DEAD_CARON 0x8a
-#define J_VK_DEAD_CEDILLA 0x8b
-#define J_VK_DEAD_OGONEK 0x8c
-#define J_VK_DEAD_IOTA 0x8d
-#define J_VK_DEAD_VOICED_SOUND 0x8e
-#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f
-#define J_VK_AMPERSAND 0x96
-#define J_VK_ASTERISK 0x97
-#define J_VK_QUOTEDBL 0x98
-#define J_VK_LESS 0x99
-#define J_VK_GREATER 0xa0
-#define J_VK_BRACELEFT 0xa1
-#define J_VK_BRACERIGHT 0xa2
-#define J_VK_AT 0x0200
-#define J_VK_COLON 0x0201
-#define J_VK_CIRCUMFLEX 0x0202
-#define J_VK_DOLLAR 0x0203
-#define J_VK_EURO_SIGN 0x0204
-#define J_VK_EXCLAMATION_MARK 0x0205
-#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206
-#define J_VK_LEFT_PARENTHESIS 0x0207
-#define J_VK_NUMBER_SIGN 0x0208
-#define J_VK_PLUS 0x0209
-#define J_VK_RIGHT_PARENTHESIS 0x020A
-#define J_VK_UNDERSCORE 0x020B
-#define J_VK_WINDOWS 0x020C
-#define J_VK_CONTEXT_MENU 0x020D
-#define J_VK_FINAL 0x0018
-#define J_VK_CONVERT 0x001C
-#define J_VK_NONCONVERT 0x001D
-#define J_VK_ACCEPT 0x001E
-#define J_VK_MODECHANGE 0x001F
-#define J_VK_KANA 0x0015
-#define J_VK_KANJI 0x0019
-#define J_VK_ALPHANUMERIC 0x00F0
-#define J_VK_KATAKANA 0x00F1
-#define J_VK_HIRAGANA 0x00F2
-#define J_VK_FULL_WIDTH 0x00F3
-#define J_VK_HALF_WIDTH 0x00F4
-#define J_VK_ROMAN_CHARACTERS 0x00F5
-#define J_VK_ALL_CANDIDATES 0x0100
-#define J_VK_PREVIOUS_CANDIDATE 0x0101
-#define J_VK_CODE_INPUT 0x0102
-#define J_VK_JAPANESE_KATAKANA 0x0103
-#define J_VK_JAPANESE_HIRAGANA 0x0104
-#define J_VK_JAPANESE_ROMAN 0x0105
-#define J_VK_KANA_LOCK 0x0106
-#define J_VK_INPUT_METHOD_ON_OFF 0x0107
-#define J_VK_CUT 0xFFD1
-#define J_VK_COPY 0xFFCD
-#define J_VK_PASTE 0xFFCF
-#define J_VK_UNDO 0xFFCB
-#define J_VK_AGAIN 0xFFC9
-#define J_VK_FIND 0xFFD0
-#define J_VK_PROPS 0xFFCA
-#define J_VK_STOP 0xFFC8
-#define J_VK_COMPOSE 0xFF20
-#define J_VK_ALT_GRAPH 0xFF7E
-#define J_VK_BEGIN 0xFF58
-#define J_VK_UNDEFINED 0x0
+
+#define J_VK_UNDEFINED ( 0x0U )
+#define J_VK_HOME ( 0x02U )
+#define J_VK_END ( 0x03U )
+#define J_VK_FINAL ( 0x04U )
+#define J_VK_PRINTSCREEN ( 0x05U )
+#define J_VK_BACK_SPACE ( 0x08U )
+#define J_VK_TAB ( 0x09U )
+#define J_VK_PAGE_DOWN ( 0x0BU )
+#define J_VK_CLEAR ( 0x0CU )
+#define J_VK_ENTER ( 0x0DU )
+#define J_VK_SHIFT ( 0x0FU )
+#define J_VK_PAGE_UP ( 0x10U )
+#define J_VK_CONTROL ( 0x11U )
+#define J_VK_ALT ( 0x12U )
+#define J_VK_ALT_GRAPH ( 0x13U )
+#define J_VK_CAPS_LOCK ( 0x14U )
+#define J_VK_PAUSE ( 0x16U )
+#define J_VK_SCROLL_LOCK ( 0x17U )
+#define J_VK_CANCEL ( 0x18U )
+#define J_VK_INSERT ( 0x1AU )
+#define J_VK_ESCAPE ( 0x1BU )
+#define J_VK_CONVERT ( 0x1CU )
+#define J_VK_NONCONVERT ( 0x1DU )
+#define J_VK_ACCEPT ( 0x1EU )
+#define J_VK_MODECHANGE ( 0x1FU )
+
+//
+// Unicode: Printable [0x20 - 0x7E]
+//
+
+#define J_VK_SPACE ( 0x20U )
+#define J_VK_EXCLAMATION_MARK ( 0x21U )
+#define J_VK_QUOTEDBL ( 0x22U )
+#define J_VK_NUMBER_SIGN ( 0x23U )
+#define J_VK_DOLLAR ( 0x24U )
+#define J_VK_PERCENT ( 0x25U )
+#define J_VK_AMPERSAND ( 0x26U )
+#define J_VK_QUOTE ( 0x27U )
+#define J_VK_LEFT_PARENTHESIS ( 0x28U )
+#define J_VK_RIGHT_PARENTHESIS ( 0x29U )
+#define J_VK_ASTERISK ( 0x2AU )
+#define J_VK_PLUS ( 0x2BU )
+#define J_VK_COMMA ( 0x2CU )
+#define J_VK_MINUS ( 0x2DU )
+#define J_VK_PERIOD ( 0x2EU )
+#define J_VK_SLASH ( 0x2FU )
+#define J_VK_0 ( 0x30U )
+#define J_VK_1 ( 0x31U )
+#define J_VK_2 ( 0x32U )
+#define J_VK_3 ( 0x33U )
+#define J_VK_4 ( 0x34U )
+#define J_VK_5 ( 0x35U )
+#define J_VK_6 ( 0x36U )
+#define J_VK_7 ( 0x37U )
+#define J_VK_8 ( 0x38U )
+#define J_VK_9 ( 0x39U )
+#define J_VK_COLON ( 0x3AU )
+#define J_VK_SEMICOLON ( 0x3BU )
+#define J_VK_LESS ( 0x3CU )
+#define J_VK_EQUALS ( 0x3DU )
+#define J_VK_GREATER ( 0x3EU )
+#define J_VK_QUESTIONMARK ( 0x3FU )
+#define J_VK_AT ( 0x40U )
+#define J_VK_A ( 0x41U )
+#define J_VK_B ( 0x42U )
+#define J_VK_C ( 0x43U )
+#define J_VK_D ( 0x44U )
+#define J_VK_E ( 0x45U )
+#define J_VK_F ( 0x46U )
+#define J_VK_G ( 0x47U )
+#define J_VK_H ( 0x48U )
+#define J_VK_I ( 0x49U )
+#define J_VK_J ( 0x4AU )
+#define J_VK_K ( 0x4BU )
+#define J_VK_L ( 0x4CU )
+#define J_VK_M ( 0x4DU )
+#define J_VK_N ( 0x4EU )
+#define J_VK_O ( 0x4FU )
+#define J_VK_P ( 0x50U )
+#define J_VK_Q ( 0x51U )
+#define J_VK_R ( 0x52U )
+#define J_VK_S ( 0x53U )
+#define J_VK_T ( 0x54U )
+#define J_VK_U ( 0x55U )
+#define J_VK_V ( 0x56U )
+#define J_VK_W ( 0x57U )
+#define J_VK_X ( 0x58U )
+#define J_VK_Y ( 0x59U )
+#define J_VK_Z ( 0x5AU )
+#define J_VK_OPEN_BRACKET ( 0x5BU )
+#define J_VK_BACK_SLASH ( 0x5CU )
+#define J_VK_CLOSE_BRACKET ( 0x5DU )
+#define J_VK_CIRCUMFLEX ( 0x5EU )
+#define J_VK_UNDERSCORE ( 0x5FU )
+#define J_VK_BACK_QUOTE ( 0x60U )
+#define J_VK_F1 ( 0x60U+ 1U )
+#define J_VK_F2 ( 0x60U+ 2U )
+#define J_VK_F3 ( 0x60U+ 3U )
+#define J_VK_F4 ( 0x60U+ 4U )
+#define J_VK_F5 ( 0x60U+ 5U )
+#define J_VK_F6 ( 0x60U+ 6U )
+#define J_VK_F7 ( 0x60U+ 7U )
+#define J_VK_F8 ( 0x60U+ 8U )
+#define J_VK_F9 ( 0x60U+ 9U )
+#define J_VK_F10 ( 0x60U+10U )
+#define J_VK_F11 ( 0x60U+11U )
+#define J_VK_F12 ( 0x60U+12U )
+#define J_VK_F13 ( 0x60U+13U )
+#define J_VK_F14 ( 0x60U+14U )
+#define J_VK_F15 ( 0x60U+15U )
+#define J_VK_F16 ( 0x60U+16U )
+#define J_VK_F17 ( 0x60U+17U )
+#define J_VK_F18 ( 0x60U+18U )
+#define J_VK_F19 ( 0x60U+19U )
+#define J_VK_F20 ( 0x60U+20U )
+#define J_VK_F21 ( 0x60U+21U )
+#define J_VK_F22 ( 0x60U+22U )
+#define J_VK_F23 ( 0x60U+23U )
+#define J_VK_F24 ( 0x60U+24U )
+#define J_VK_LEFT_BRACE ( 0x7BU )
+#define J_VK_PIPE ( 0x7CU )
+#define J_VK_RIGHT_BRACE ( 0x7DU )
+#define J_VK_TILDE ( 0x7EU )
+
+//
+// Unicode: Non printable controls: [0x7F - 0x9F]
+//
+
+#define J_VK_SEPARATOR ( 0x7FU )
+#define J_VK_NUMPAD0 ( 0x80U )
+#define J_VK_NUMPAD1 ( 0x81U )
+#define J_VK_NUMPAD2 ( 0x82U )
+#define J_VK_NUMPAD3 ( 0x83U )
+#define J_VK_NUMPAD4 ( 0x84U )
+#define J_VK_NUMPAD5 ( 0x85U )
+#define J_VK_NUMPAD6 ( 0x86U )
+#define J_VK_NUMPAD7 ( 0x87U )
+#define J_VK_NUMPAD8 ( 0x88U )
+#define J_VK_NUMPAD9 ( 0x89U )
+#define J_VK_DECIMAL ( 0x8AU )
+#define J_VK_ADD ( 0x8BU )
+#define J_VK_SUBTRACT ( 0x8CU )
+#define J_VK_MULTIPLY ( 0x8DU )
+#define J_VK_DIVIDE ( 0x8EU )
+
+#define J_VK_DELETE ( 0x93U )
+#define J_VK_NUM_LOCK ( 0x94U )
+#define J_VK_LEFT ( 0x95U )
+#define J_VK_UP ( 0x96U )
+#define J_VK_RIGHT ( 0x97U )
+#define J_VK_DOWN ( 0x98U )
+#define J_VK_CONTEXT_MENU ( 0x99U )
+#define J_VK_WINDOWS ( 0x9AU )
+#define J_VK_META ( 0x9BU )
+#define J_VK_HELP ( 0x9CU )
+#define J_VK_COMPOSE ( 0x9DU )
+#define J_VK_BEGIN ( 0x9EU )
+#define J_VK_STOP ( 0x9FU )
+
+//
+// Unicode: Printable [0x00A0 - 0xDFFF]
+//
+
+#define J_VK_INVERTED_EXCLAMATION_MARK ( 0xA1U )
+#define J_VK_EURO_SIGN ( 0x20ACU )
+
+//
+// Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
+//
+
+/* for Sun keyboards */
+#define J_VK_CUT ( 0xF879U )
+#define J_VK_COPY ( 0xF87AU )
+#define J_VK_PASTE ( 0xF87BU )
+#define J_VK_UNDO ( 0xF87CU )
+#define J_VK_AGAIN ( 0xF87DU )
+#define J_VK_FIND ( 0xF87EU )
+#define J_VK_PROPS ( 0xF87FU )
+
+/* for input method support on Asian Keyboards */
+#define J_VK_INPUT_METHOD_ON_OFF ( 0xF890U )
+#define J_VK_CODE_INPUT ( 0xF891U )
+#define J_VK_ROMAN_CHARACTERS ( 0xF892U )
+#define J_VK_ALL_CANDIDATES ( 0xF893U )
+#define J_VK_PREVIOUS_CANDIDATE ( 0xF894U )
+#define J_VK_ALPHANUMERIC ( 0xF895U )
+#define J_VK_KATAKANA ( 0xF896U )
+#define J_VK_HIRAGANA ( 0xF897U )
+#define J_VK_FULL_WIDTH ( 0xF898U )
+#define J_VK_HALF_WIDTH ( 0xF89AU )
+#define J_VK_JAPANESE_KATAKANA ( 0xF89BU )
+#define J_VK_JAPANESE_HIRAGANA ( 0xF89CU )
+#define J_VK_JAPANESE_ROMAN ( 0xF89DU )
+#define J_VK_KANA_LOCK ( 0xF89FU )
+
+#define J_VK_KEYBOARD_INVISIBLE ( 0xF8FFU )
#endif
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 01cbd80ec..25ea47c47 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -33,7 +33,7 @@
#import <inttypes.h>
-#import "jogamp_newt_driver_macosx_MacWindow.h"
+#import "jogamp_newt_driver_macosx_WindowDriver.h"
#import "NewtMacWindow.h"
#import "MouseEvent.h"
@@ -62,12 +62,36 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
return str;
}
-static void setFrameTopLeftPoint(NSWindow* pWin, NewtMacWindow* mWin, jint x, jint y) {
- NSPoint pS = [mWin newtScreenWinPos2OSXScreenPos: NSMakePoint(x, y)];
+static void setWindowClientTopLeftPoint(NewtMacWindow* mWin, jint x, jint y, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)];
+ DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y);
+
[mWin setFrameOrigin: pS];
+ DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+ if( doDisplay ) {
+ NSView* mView = [mWin contentView];
+ [mWin invalidateCursorRectsForView: mView];
+ }
+}
- NSView* mView = [mWin contentView];
- [mWin invalidateCursorRectsForView: mView];
+static void setWindowClientTopLeftPointAndSize(NewtMacWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+ NSSize clientSZ = NSMakeSize(width, height);
+ NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ];
+ NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ];
+ NSRect rect = { pS, topSZ };
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ [mWin setFrame: rect display:doDisplay];
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ // -> display:YES
+ // if( doDisplay ) {
+ // NSView* mView = [mWin contentView];
+ // [mWin invalidateCursorRectsForView: mView];
+ // }
}
#ifdef VERBOSE_ON
@@ -76,58 +100,67 @@ static int getRetainCount(NSObject * obj) {
}
#endif
-static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView) {
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtView *view, BOOL enable) {
+ DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+ if( !enable) {
+ jobject globJavaWindowObject = [view getJavaWindowObject];
+ if( NULL != globJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [view setJavaWindowObject: NULL];
+ }
+ } else if( NULL != newJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+ [view setJavaWindowObject: globJavaWindowObject];
+ }
+ DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtMacWindow *win, NewtView *newView, BOOL setJavaWindow) {
NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
+ NewtView* oldNewtView = NULL;
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
+ if( [oldNSView isKindOfClass:[NewtView class]] ) {
+ oldNewtView = (NewtView *) oldNSView;
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView), pview);
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView), pview);
- if(NULL!=oldNSView) {
+ if( NULL!=oldNSView ) {
NS_DURING
// Available >= 10.5 - Makes the menubar disapear
- if([oldNSView isInFullScreenMode]) {
+ BOOL iifs;
+ if ( [oldNSView respondsToSelector:@selector(isInFullScreenMode)] ) {
+ iifs = [oldNSView isInFullScreenMode];
+ } else {
+ iifs = NO;
+ }
+ if(iifs && [oldNSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) {
[oldNSView exitFullScreenModeWithOptions: NULL];
}
NS_HANDLER
NS_ENDHANDLER
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n",
- dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtView, newView, getRetainCount(newView));
- if( NULL != oldView ) {
- jobject globJavaWindowObject = [oldView getJavaWindowObject];
- (*env)->DeleteGlobalRef(env, globJavaWindowObject);
- [oldView setJavaWindowObject: NULL];
- [oldView setDestroyNotifySent: false];
+ if( NULL != oldNewtView ) {
+ [oldNewtView setDestroyNotifySent: false];
+ setJavaWindowObject(env, NULL, oldNewtView, NO);
}
[oldNSView removeFromSuperviewWithoutNeedingDisplay];
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
- if(NULL!=newView) {
- jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject);
- [newView setJavaWindowObject: globJavaWindowObject];
+ if( NULL!=newView ) {
[newView setDestroyNotifySent: false];
- {
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
- [newView setJVMHandle: jvmHandle];
- [newView setJVMVersion: jvmVersion];
+ if( setJavaWindow ) {
+ setJavaWindowObject(env, javaWindowObject, newView, YES);
}
DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n",
@@ -146,20 +179,18 @@ NS_ENDHANDLER
dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
// make sure the insets are updated in the java object
- [win updateInsets: env];
+ [win updateInsets: env jwin:javaWindowObject];
DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n",
win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView));
-
- [pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacDisplay
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
* Method: initIDs
* Signature: ()Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSApplication0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSApplication0
(JNIEnv *env, jclass clazz)
{
static int initialized = 0;
@@ -167,6 +198,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSAppli
if(initialized) return JNI_TRUE;
initialized = 1;
+ NewtCommon_init(env);
+
// This little bit of magic is needed in order to receive mouse
// motion events and allow key focus to be properly transferred.
// FIXME: are these Carbon APIs? They come from the
@@ -189,11 +222,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSAppli
}
/*
- * Class: jogamp_newt_driver_macosx_MacDisplay
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
* Method: runNSApplication0
* Signature: ()V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplication0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_runNSApplication0
(JNIEnv *env, jclass clazz)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -206,11 +239,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplicatio
}
/*
- * Class: jogamp_newt_driver_macosx_MacDisplay
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
* Method: stopNSApplication0
* Signature: ()V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_stopNSApplication0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplication0
(JNIEnv *env, jclass clazz)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -242,47 +275,123 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_stopNSApplicati
[pool release];
}
-static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) {
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- return (NSScreen *) [screens objectAtIndex: screen_idx];
+static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) {
+ if( NULL != iconData ) {
+ NSInteger iconWidth = (NSInteger) jiconWidth;
+ NSInteger iconHeight = (NSInteger) jiconHeight;
+ const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp;
+ const NSBitmapFormat bfmt = NSAlphaNonpremultipliedBitmapFormat;
+ const BOOL hasAlpha = YES;
+
+ NSBitmapImageRep* bir = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &iconData
+ pixelsWide: iconWidth
+ pixelsHigh: iconHeight
+ bitsPerSample: bpc
+ samplesPerPixel: spp
+ hasAlpha: hasAlpha
+ isPlanar: NO
+ colorSpaceName: NSCalibratedRGBColorSpace
+ bitmapFormat: bfmt
+ bytesPerRow: iconWidth*4
+ bitsPerPixel: bpp];
+ [bir autorelease];
+ NSImage* nsImage = [[NSImage alloc] initWithCGImage: [bir CGImage] size:NSZeroSize];
+ return nsImage;
+ }
+ return NULL;
}
/*
- * Class: jogamp_newt_driver_macosx_MacScreen
- * Method: getWidthImpl
- * Signature: (I)I
+ * Class: jogamp_newt_driver_macosx_DisplayDriver
+ * Method: setAppIcon0
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getWidthImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height)
{
+ if( 0 == pixels ) {
+ return;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
-
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ [NSApp setApplicationIconImage: nsImage];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
-
- return (jint) (rect.size.width);
}
-/*
- * Class: jogamp_newt_driver_macosx_MacScreen
- * Method: getHeightImpl
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0
- (JNIEnv *env, jclass clazz, jint screen_idx)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
{
+ if( 0 == pixels ) {
+ return 0;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
+ NSCursor * res = NULL;
+ if( NULL != nsImage ) {
+ [nsImage autorelease];
+ NSPoint hotP = { hotX, hotY };
+ res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP];
+ }
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ [pool release];
+ DBG_PRINT( "createPointerIcon0 %p\n", res);
+ return (jlong) (intptr_t) res;
+}
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx);
- NSRect rect = [screen frame];
-
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jobject unused, jlong handle)
+{
+ NSCursor * c = (NSCursor*) (intptr_t) handle ;
+ if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ DBG_PRINT( "destroyPointerIcon0 %p\n", c);
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [c release];
[pool release];
+}
- return (jint) (rect.size.height);
+static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx, BOOL cap) {
+ NSArray *screens = [NSScreen screens];
+ if( screen_idx<0 || screen_idx>=[screens count] ) {
+ if( cap ) {
+ screen_idx=0;
+ } else {
+ return NULL;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: screen_idx];
+}
+
+static NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) {
+ NSArray *screens = [NSScreen screens];
+ int i;
+ for(i=[screens count]-1; i>=0; i--) {
+ NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+ NSRect frame = [screen frame];
+ if( x >= frame.origin.x &&
+ y >= frame.origin.y &&
+ x < frame.origin.x + frame.size.width &&
+ y < frame.origin.y + frame.size.height ) {
+ return screen;
+ }
+ }
+ return (NSScreen *) [screens objectAtIndex: 0];
}
static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
@@ -318,12 +427,12 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
#define ROTMODES_PER_REALMODE 4
/*
- * Class: jogamp_newt_driver_macosx_MacScreen
- * Method: getScreenSizeMM0
+ * Class: jogamp_newt_driver_macosx_ScreenDriver
+ * Method: getMonitorProps0
* Signature: (I)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSizeMM0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -333,33 +442,46 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSi
timespec_now(&t0);
#endif
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
#endif
-
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
#endif
- CGSize screenDim = CGDisplayScreenSize(display);
+ CGSize sizeMM = CGDisplayScreenSize(display);
#ifdef DBG_PERF
timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL);
+ fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL);
#endif
- jint prop[ 2 ];
- prop[0] = (jint) screenDim.width;
- prop[1] = (jint) screenDim.height;
-
- jintArray properties = (*env)->NewIntArray(env, 2);
+ CGRect bounds = CGDisplayBounds (display);
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int offset = 0;
+ prop[offset++] = propCount;
+ prop[offset++] = crt_idx;
+ prop[offset++] = (jint) sizeMM.width;
+ prop[offset++] = (jint) sizeMM.height;
+ prop[offset++] = (jint) bounds.origin.x; // rotated viewport x
+ prop[offset++] = (jint) bounds.origin.y; // rotated viewport y
+ prop[offset++] = (jint) bounds.size.width; // rotated viewport width
+ prop[offset++] = (jint) bounds.size.height; // rotated viewport height
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
}
- (*env)->SetIntArrayRegion(env, properties, 0, 2, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
[pool release];
@@ -367,17 +489,20 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSi
}
/*
- * Class: jogamp_newt_driver_macosx_MacScreen
- * Method: getScreenMode0
- * Signature: (IIII)[I
+ * Class: jogamp_newt_driver_macosx_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (II)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jint crt_idx, jint mode_idx)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
@@ -386,12 +511,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
CFDictionaryRef mode = NULL;
int currentCCWRot = (int)CGDisplayRotation(display);
jint ccwRot = 0;
+ int nativeId = 0;
#ifdef VERBOSE_ON
if(0 >= mode_idx) {
// only for current mode (-1) and first mode (scanning)
DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
+ (int)crt_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
}
#endif
@@ -400,16 +526,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
(int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
[pool release];
- return (*env)->NewIntArray(env, 0);
+ return NULL;
} else if(-1 < mode_idx) {
// only at initialization time, where index >= 0
- prop_num++; // add 1st extra prop, mode_idx
- mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
+ nativeId = mode_idx / ROTMODES_PER_REALMODE;
ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
} else {
// current mode
mode = CGDisplayCurrentMode(display);
ccwRot = currentCCWRot;
+ CFRange range = CFRangeMake (0, numberOfAvailableModes);
+ nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode);
}
// mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
@@ -423,34 +551,30 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
mHeight = tempWidth;
}
- jint prop[ prop_num ];
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- int propIndexRes = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
- prop[propIndex++] = 0; // set later for verification of iterator
- propIndexRes = propIndex;
+ int refreshRate = CGDDGetModeRefreshRate(mode);
+ int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = mWidth;
prop[propIndex++] = mHeight;
prop[propIndex++] = CGDDGetModeBitsPerPixel(mode);
- prop[propIndex++] = widthMM;
- prop[propIndex++] = heightMM;
- prop[propIndex++] = CGDDGetModeRefreshRate(mode);
+ prop[propIndex++] = fRefreshRate * 100; // Hz*100
+ prop[propIndex++] = 0; // flags
+ prop[propIndex++] = nativeId;
prop[propIndex++] = ccwRot;
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
- DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n",
+ DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
(int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes,
- (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2],
- (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]);
+ (int)prop[1], (int)prop[2], (int)prop[3],
+ (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
// CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
[pool release];
@@ -459,37 +583,48 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
}
/*
- * Class: jogamp_newt_driver_macosx_MacScreen
- * Method: setScreenMode0
- * Signature: (II)Z
+ * Class: jogamp_newt_driver_macosx_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (III)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint crt_idx, jint nativeId, jint ccwRot)
{
jboolean res = JNI_TRUE;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)crt_idx, false);
+ if( NULL == screen ) {
+ [pool release];
+ return JNI_FALSE;
+ }
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
-#ifdef VERBOSE_ON
CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes);
+#ifdef VERBOSE_ON
CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
#endif
- CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
- // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
- int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
- DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n",
- (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+ DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), nativeID %d, rot %d ccw, avail: %d/%d\n",
+ (int)crt_idx, screen, (void*)(intptr_t)display, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+
+ CFDictionaryRef mode = NULL;
- if(ccwRot!=0) {
+ if( 0 != ccwRot ) {
// FIXME: How to rotate the display/screen on OSX programmatically ?
DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot);
res = JNI_FALSE;
+ } else {
+ if( numberOfAvailableModes <= nativeId ) {
+ res = JNI_FALSE;
+ } else {
+ mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId);
+ // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+ }
}
- if(JNI_TRUE == res) {
+
+ if( NULL != mode ) {
CGError err = CGDisplaySwitchToMode(display, mode);
if(kCGErrorSuccess != err) {
DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err);
@@ -504,11 +639,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMod
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: initIDs
* Signature: ()Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0
(JNIEnv *env, jclass clazz)
{
static int initialized = 0;
@@ -516,19 +651,21 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0
if(initialized) return JNI_TRUE;
initialized = 1;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
- NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNamePoint);
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't find %s", ClazzNamePoint);
}
pointClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==pointClz) {
- NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNamePoint);
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't use %s", ClazzNamePoint);
}
pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
if(NULL==pointCstr) {
- NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't fetch %s.%s %s",
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
@@ -537,51 +674,138 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0
// printf("Going to sleep for 10 seconds\n");
// sleep(10);
- return (jboolean) [NewtMacWindow initNatives: env forClass: clazz];
+ BOOL res = [NewtMacWindow initNatives: env forClass: clazz];
+ [pool release];
+
+ return (jboolean) res;
}
-/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+/**
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: createView0
+ * Signature: (IIIIZ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createView0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, fs %d (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen);
+
+ NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y);
+ NSRect rectWin;
+
+ if (fullscreen) {
+ rectWin = [myScreen frame];
+ x = 0;
+ y = 0;
+ w = (jint) (rectWin.size.width);
+ h = (jint) (rectWin.size.height);
+ } else {
+ rectWin = NSMakeRect(x, y, w, h);
+ }
+
+ NSRect rectView = NSMakeRect(0, 0, w, h);
+ NewtView *myView = [[NewtView alloc] initWithFrame: rectView] ;
+ DBG_PRINT( "createView0.X - new view: %p\n", myView);
+
+ [pool release];
+
+ return (jlong) (intptr_t) myView;
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: createWindow0
- * Signature: (JIIIIZIIIJ)J
+ * Signature: (IIIIZIIJ)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
- (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean opaque, jboolean fullscreen, jint styleMask,
- jint bufferingType, jint screen_idx, jlong jview)
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* myView = (NewtView*) (intptr_t) jview ;
- DBG_PRINT( "createWindow0 - %p (this), %p (parent), %d/%d %dx%d, opaque %d, fs %d, style %X, buffType %X, screenidx %d, view %p (START)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, (int)x, (int)y, (int)w, (int)h, (int) opaque, (int)fullscreen,
- (int)styleMask, (int)bufferingType, (int)screen_idx, myView);
+ DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen,
+ (int)styleMask, (int)bufferingType, myView);
+ (void)myView;
- NSArray *screens = [NSScreen screens];
- if(screen_idx<0) screen_idx=0;
- if(screen_idx>=[screens count]) screen_idx=0;
- NSScreen *myScreen = (NSScreen *) [screens objectAtIndex: screen_idx];
- NSRect rect;
+ NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y);
+ NSRect rectWin;
if (fullscreen) {
styleMask = NSBorderlessWindowMask;
- rect = [myScreen frame];
+ rectWin = [myScreen frame];
x = 0;
y = 0;
- w = (jint) (rect.size.width);
- h = (jint) (rect.size.height);
+ w = (jint) (rectWin.size.width);
+ h = (jint) (rectWin.size.height);
} else {
- rect = NSMakeRect(x, y, w, h);
+ rectWin = NSMakeRect(x, y, w, h);
}
// Allocate the window
- NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect
+ NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rectWin
styleMask: (NSUInteger) styleMask
backing: (NSBackingStoreType) bufferingType
- defer: NO
- screen: myScreen
+ defer: YES
isFullscreenWindow: fullscreen];
- [myWindow setReleasedWhenClosed: YES]; // default
+ // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) myWindow);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: initWindow0
+ * Signature: (JJIIIIZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h,
+ jboolean opaque, jboolean visible, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtMacWindow* myWindow = (NewtMacWindow*) ((intptr_t) window);
+ NewtView* myView = (NewtView*) (intptr_t) jview ;
+ BOOL fullscreen = myWindow->isFullscreenWindow;
+
+ DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, opaque %d, fs %d, visible %d, view %p (START)\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h,
+ (int) opaque, (int)fullscreen, (int)visible, myView);
+
+ NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y);
+
+ NSRect rectWin;
+ if (fullscreen) {
+ rectWin = [myScreen frame];
+ x = 0;
+ y = 0;
+ w = (jint) (rectWin.size.width);
+ h = (jint) (rectWin.size.height);
+ } else {
+ rectWin = NSMakeRect(x, y, w, h);
+ }
+
+ [myWindow setReleasedWhenClosed: NO]; // We control NSWindow destruction!
[myWindow setPreservesContentDuringLiveResize: NO];
+NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setRestorable:)] ) {
+ // Available >= 10.7 - Removes restauration 'feature', really close
+ [myWindow setRestorable: NO];
+ }
+NS_HANDLER
+NS_ENDHANDLER
NSObject* nsParentObj = (NSObject*) ((intptr_t) parent);
NSWindow* parentWindow = NULL;
@@ -589,26 +813,37 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
parentWindow = (NSWindow*) nsParentObj;
parentView = [parentWindow contentView];
- DBG_PRINT( "createWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+ DBG_PRINT( "initWindow0 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
} else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
parentView = (NSView*) nsParentObj;
parentWindow = [parentView window];
- DBG_PRINT( "createWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
+ DBG_PRINT( "initWindow0 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow);
} else {
- DBG_PRINT( "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+ DBG_PRINT( "initWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj);
+ }
+ DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+
+ // Remove animations for child windows
+ if(NULL != parentWindow) {
+NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) {
+ // Available >= 10.7 - Removes default animations
+ [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+ }
+NS_HANDLER
+NS_ENDHANDLER
}
- DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]);
#ifdef VERBOSE_ON
int dbgIdx = 1;
#endif
if(opaque) {
[myWindow setOpaque: YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
if (!fullscreen) {
[myWindow setShowsResizeIndicator: YES];
}
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
} else {
[myWindow setOpaque: NO];
[myWindow setBackgroundColor: [NSColor clearColor]];
@@ -616,117 +851,175 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
// specify we want mouse-moved events
[myWindow setAcceptsMouseMovedEvents:YES];
- DBG_PRINT( "createWindow0.%d\n", dbgIdx++);
- // Use given NewtView or allocate an NewtView if NULL
- if(NULL == myView) {
- myView = [[NewtView alloc] initWithFrame: rect] ;
- DBG_PRINT( "createWindow0.%d - use new view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- } else {
- DBG_PRINT( "createWindow0.%d - use given view: %p,%d\n", dbgIdx++, myView, getRetainCount(myView));
- }
-
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
// Set the content view
- changeContentView(env, jthis, parentView, myWindow, myView);
+ changeContentView(env, jthis, parentView, myWindow, myView, NO);
+ [myWindow setInitialFirstResponder: myView];
- DBG_PRINT( "createWindow0.%d - %p,%d view %p,%d, isVisible %d\n",
- dbgIdx++, myWindow, getRetainCount(myWindow), myView, getRetainCount(myView), [myWindow isVisible]);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
if(NULL!=parentWindow) {
[myWindow attachToParent: parentWindow];
}
- // Immediately re-position the window based on an upper-left coordinate system
- setFrameTopLeftPoint(parentWindow, myWindow, x, y);
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible], visible);
- // force surface creation
- [myView lockFocus];
- [myView unlockFocus];
+ // Immediately re-position this window based on an upper-left coordinate system
+ setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO);
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
NS_DURING
// concurrent view rendering
// Available >= 10.6 - Makes the menubar disapear
- [myWindow setAllowsConcurrentViewDrawing: YES];
- [myView setCanDrawConcurrently: YES];
-NS_HANDLER
-NS_ENDHANDLER
+ if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) {
+ [myWindow setAllowsConcurrentViewDrawing: YES];
+ }
- // visible on front
- [myWindow orderFront: myWindow];
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
-NS_DURING
- // Available >= 10.5 - Makes the menubar disapear
- if(fullscreen) {
- [myView enterFullScreenMode: myScreen withOptions:NULL];
+ if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) {
+ [myView setCanDrawConcurrently: YES];
}
NS_HANDLER
NS_ENDHANDLER
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // visible on front
+ if( visible ) {
+ [myWindow orderFront: myWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // force surface creation
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
// Set the next responder to be the window so that we can forward
// right mouse button down events
[myView setNextResponder: myWindow];
- DBG_PRINT( "createWindow0 - %p (this), %p (parent): new window: %p, view %p,%d (END)\n",
- (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView, getRetainCount(myView));
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
- [pool release];
+ [myView setDestroyNotifySent: false];
+ setJavaWindowObject(env, jthis, myView, YES);
- return (jlong) ((intptr_t) myWindow);
-}
-// Footnote: Our view handling produces random 'Assertion failure' even w/o parenting:
-//
-// [NSThemeFrame lockFocus], /SourceCache/AppKit/AppKit-1138.23/AppKit.subproj/NSView.m:6053
-// [NSThemeFrame(0x7fe94bc72c80) lockFocus] failed with window=0x7fe94bc445a0, windowNumber=9425, [self isHiddenOrHasHiddenAncestor]=0
-// ..
-// AppKit 0x00007fff89621001 -[NSView lockFocus] + 250
-// AppKit 0x00007fff8961eafa -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 3780
-// AppKit 0x00007fff8961793e -[NSView displayIfNeeded] + 1676
-// AppKit 0x00007fff8961707d _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 648
-//
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+NS_DURING
+ if( fullscreen ) {
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * allowing ALT-TAB to allow process/app switching!
+ * Shall have no penalty on modern GPU and is also recommended, see bottom box @
+ * <https://developer.apple.com/library/mac/documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html>
+ *
+ if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) {
+ // Available >= 10.5 - Makes the menubar disapear
+ [myView enterFullScreenMode: myScreen withOptions:NULL];
+ } */
+ if( myWindow->hasPresentationSwitch ) {
+ DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n",
+ dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions);
+ [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions];
+ }
+ }
+NS_HANDLER
+NS_ENDHANDLER
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
-/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ [pool release];
+ DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: close0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0
(JNIEnv *env, jobject unused, jlong window)
{
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n");
+ return;
+ }
+ BOOL isNSWin = [mWin isKindOfClass:[NSWindow class]];
+ BOOL isNewtWin = [mWin isKindOfClass:[NewtMacWindow class]];
+ NSWindow *pWin = [mWin parentWindow];
+ DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
+ if( !isNewtWin ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* mView = (NewtView *)[mWin contentView];
- NSWindow* pWin = [mWin parentWindow];
- BOOL destroyNotifySent = (NULL != mView) ? [mView getDestroyNotifySent] : false;
+ BOOL fullscreen = mWin->isFullscreenWindow;
+ BOOL destroyNotifySent, isNSView, isNewtView;
+ if( NULL != mView ) {
+ isNSView = [mView isKindOfClass:[NSView class]];
+ isNewtView = [mView isKindOfClass:[NewtView class]];
+ destroyNotifySent = isNewtView ? [mView getDestroyNotifySent] : false;
+ } else {
+ isNSView = false;
+ isNewtView = false;
+ destroyNotifySent = false;
+ }
- DBG_PRINT( "windowClose.0 - %p,%d, destroyNotifySent %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtView %d], fullscreen %d, parent %p\n",
+ mWin, destroyNotifySent, mView, isNSView, isNewtView, (int)fullscreen, pWin);
- [mWin setUnrealized];
+ [mWin setRealized: NO];
- if(NULL!=mView) {
+ if( isNewtView ) {
// cleanup view
- jobject javaWindowObject = [mView getJavaWindowObject];
[mView setDestroyNotifySent: true];
- if(NULL!=javaWindowObject) {
- DBG_PRINT( "windowClose.0: Clear global javaWindowObject reference (%p)\n", javaWindowObject);
- (*env)->DeleteGlobalRef(env, javaWindowObject);
- [mView setJavaWindowObject: NULL];
- }
+ setJavaWindowObject(env, NULL, mView, NO);
}
NS_DURING
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * See initWindow0(..) above ..
if(NULL!=mView) {
- // Available >= 10.5 - Makes the menubar disapear
- if([mView isInFullScreenMode]) {
+ BOOL iifs;
+ if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) {
+ iifs = [mView isInFullScreenMode];
+ } else {
+ iifs = NO;
+ }
+ if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) {
[mView exitFullScreenModeWithOptions: NULL];
}
- // Note: mWin's release will also release it's mView!
- // [mWin setContentView: nil];
- // [mView release];
+ } */
+ // Note: mWin's release will also release it's mView!
+ DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n",
+ mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions);
+
+ if( fullscreen && mWin->hasPresentationSwitch ) {
+ DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n",
+ mWin, mView, (int)mWin->defaultPresentationOptions);
+ [NSApp setPresentationOptions: mWin->defaultPresentationOptions];
}
NS_HANDLER
NS_ENDHANDLER
@@ -736,65 +1029,55 @@ NS_ENDHANDLER
}
[mWin orderOut: mWin];
- DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin);
- // Only release window, if release is not yet in process.
- // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked.
- if(!destroyNotifySent) {
- // '[mWin close]' causes a crash at exit.
- // This probably happens b/c it sends events to the main loop
- // but our resources are gone ?!
- // However, issuing a simple release seems to work quite well.
- // [mWin release];
- [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
- }
+ [mWin release];
- DBG_PRINT( "windowClose.X - %p,%d, released %d, view %p,%d, parent %p\n",
- mWin, getRetainCount(mWin), !destroyNotifySent, mView, getRetainCount(mView), pWin);
+ DBG_PRINT( "windowClose.Xp\n");
[pool release];
}
/*
- * Class: Java_jogamp_newt_driver_macosx_MacWindow
+ * Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: lockSurface0
- * Signature: (J)Z
+ * Signature: (JJ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_lockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
if(NO == [mWin isRealized]) {
return JNI_FALSE;
}
- NewtView * mView = (NewtView *) [mWin contentView];
+ NewtView * mView = (NewtView *) ((intptr_t) view);
return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
}
/*
- * Class: Java_jogamp_newt_driver_macosx_MacWindow
+ * Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: unlockSurface0
- * Signature: (J)V
+ * Signature: (JJ)Z
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_unlockSurface0
- (JNIEnv *env, jclass clazz, jlong window)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
{
- NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- NewtView * mView = (NewtView *) [mWin contentView];
- [mView softUnlock];
+ // NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
+ (void) window;
+ NewtView * mView = (NewtView *) ((intptr_t) view);
+ return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
/** deadlocks, since we render independent of focus
[mView unlockFocus]; */
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: requestFocus0
* Signature: (JZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0
(JNIEnv *env, jobject window, jlong w, jboolean force)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -802,15 +1085,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
#endif
-
DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
+ [mWin setAcceptsMouseMovedEvents: YES];
[mWin makeFirstResponder: nil];
- [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderFrontRegardless];
- // [mWin makeKeyWindow];
+ [mWin orderFrontRegardless];
+ [mWin makeKeyWindow];
DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
@@ -818,75 +1098,75 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
- * Method: requestFocusParent0
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: resignFocus0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0
(JNIEnv *env, jobject window, jlong w)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) w);
NSWindow* pWin = [mWin parentWindow];
-#ifdef VERBOSE_ON
BOOL hasFocus = [mWin isKeyWindow];
-#endif
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
- if(NULL != pWin) {
- [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [pWin makeKeyWindow];
+ DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ if( hasFocus ) {
+ if(NULL != pWin) {
+ // [mWin makeFirstResponder: pWin];
+ [pWin makeKeyWindow];
+ } else {
+ [pWin resignKeyWindow];
+ }
}
- DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin);
+ DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin);
[pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: orderFront0
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSWindow* mWin = (NSWindow*) ((intptr_t) window);
+ NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderFront0 - window: %p (START)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [win orderFrontRegardless];
+ if( NULL == pWin ) {
+ [mWin orderFrontRegardless];
+ } else {
+ [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]];
+ }
- DBG_PRINT( "orderFront0 - window: %p (END)\n", win);
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
[pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: orderOut
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* mWin = (NSWindow*) ((intptr_t) window);
NSWindow* pWin = [mWin parentWindow];
- DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin);
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
- if(NULL == pWin) {
- [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderOut: mWin];
+ if( NULL == pWin ) {
+ [mWin orderOut: mWin];
} else {
- [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES];
- // This will occasionally cause a free of non allocated object crash:
- // [mWin orderBack: mWin];
+ [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]];
}
DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
@@ -895,11 +1175,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: setTitle0
* Signature: (JLjava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setTitle0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0
(JNIEnv *env, jobject unused, jlong window, jstring title)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -917,47 +1197,47 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setTitle0
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
- * Method: contentView
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: contentView0
* Signature: (J)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_contentView0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0
(JNIEnv *env, jobject unused, jlong window)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NSView* nsView = [win contentView];
+ NewtView* newtView = NULL;
- DBG_PRINT( "contentView0 - window: %p (START)\n", win);
+ if( [nsView isKindOfClass:[NewtView class]] ) {
+ newtView = (NewtView *) nsView;
+ }
- jlong res = (jlong) ((intptr_t) [win contentView]);
+ DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView);
- DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+ jlong res = (jlong) ((intptr_t) nsView);
[pool release];
return res;
}
-/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: changeContentView
- * Signature: (J)J
+ * Signature: (J)V
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_changeContentView0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0
(JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtView* newView = (NewtView *) ((intptr_t) jview);
NewtMacWindow* win = (NewtMacWindow*) ((intptr_t) window);
- NSView* oldNSView = [win contentView];
- NewtView* oldView = NULL;
- if( [oldNSView isMemberOfClass:[NewtView class]] ) {
- oldView = (NewtView *) oldNSView;
- }
-
- DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n",
+ win, newView, getRetainCount(newView));
NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
NSView* pView = NULL;
@@ -970,78 +1250,65 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_changeContentVi
}
}
- changeContentView(env, jthis, pView, win, newView);
+ changeContentView(env, jthis, pView, win, newView, YES);
- DBG_PRINT( "changeContentView0.X - win %p, view (%p,%d (%d) -> %p,%d)\n",
- win, oldNSView, getRetainCount(oldNSView), NULL!=oldView, newView, getRetainCount(newView));
+ DBG_PRINT( "changeContentView0.X\n");
[pool release];
-
- return (jlong) ((intptr_t) oldView);
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
- * Method: setContentSize
- * Signature: (JII)V
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setContentSize0
- (JNIEnv *env, jobject unused, jlong window, jint w, jint h)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSWindow* win = (NSWindow*) ((intptr_t) window);
+ NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- DBG_PRINT( "setContentSize0 - window: %p (START)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
- NSSize sz = NSMakeSize(w, h);
- [win setContentSize: sz];
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
- DBG_PRINT( "setContentSize0 - window: %p (END)\n", win);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
[pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
- * Method: setFrameTopLeftPoint
- * Signature: (JJII)V
+ * Class: jogamp_newt_driver_macosx_WindowDriver
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setFrameTopLeftPoint0
- (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NewtMacWindow* mWin = (NewtMacWindow*) ((intptr_t) window);
- NSObject *nsParentObj = (NSObject*) ((intptr_t) parent);
- NSWindow* pWin = NULL;
- if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) {
- pWin = (NSWindow*) nsParentObj;
- } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) {
- NSView* pView = (NSView*) nsParentObj;
- pWin = [pView window];
- }
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin);
+ setWindowClientTopLeftPoint(mWin, x, y, display);
- setFrameTopLeftPoint(pWin, mWin, x, y);
-
- DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin);
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
[pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: setAlwaysOnTop0
* Signature: (JZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setAlwaysOnTop0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTop0
(JNIEnv *env, jobject unused, jlong window, jboolean atop)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (START)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (START)\n", win, (int)atop);
if(atop) {
[win setLevel:NSFloatingWindowLevel];
@@ -1049,68 +1316,118 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setAlwaysOnTop0
[win setLevel:NSNormalWindowLevel];
}
- DBG_PRINT( "setAlwaysOnTop0 - window: %p (END)\n", win);
+ DBG_PRINT( "setAlwaysOnTop0 - window: %p, atop %d (END)\n", win, (int)atop);
[pool release];
}
/*
- * Class: jogamp_newt_driver_macosx_MacWindow
+ * Class: jogamp_newt_driver_macosx_WindowDriver
* Method: getLocationOnScreen0
* Signature: (JII)Ljavax/media/nativewindow/util/Point;
*/
-JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOnScreen0
+JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0
(JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
{
- NSObject *nsObj = (NSObject*) ((intptr_t) win);
- NewtMacWindow * mWin = NULL;
-
- if( [nsObj isKindOfClass:[NewtMacWindow class]] ) {
- mWin = (NewtMacWindow*) nsObj;
- } else {
- NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj);
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) win;
+ if( ![mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return NULL;
}
-
NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)];
return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y);
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jobject unused, jlong window, jlong handle)
+{
+ NSCursor *c = (NSCursor*) (intptr_t) handle ;
+ if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c);
+ return;
+ }
+ NewtMacWindow *mWin = (NewtMacWindow*) (intptr_t) window;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setPointerIcon: c];
+ [pool release];
+}
+
/*
- * Class: Java_jogamp_newt_driver_macosx_MacWindow
+ * Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: setPointerVisible0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVisible0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0
(JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
- hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
+ hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
+ [pool release];
}
/*
- * Class: Java_jogamp_newt_driver_macosx_MacWindow
+ * Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: confinePointer0
* Signature: (JZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_confinePointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0
(JNIEnv *env, jclass clazz, jlong window, jboolean confine)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
- return JNI_TRUE;
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO];
+ [pool release];
}
/*
- * Class: Java_jogamp_newt_driver_macosx_MacWindow
+ * Class: Java_jogamp_newt_driver_macosx_WindowDriver
* Method: warpPointer0
* Signature: (JJII)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_warpPointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMousePosition: [mWin newtClientWinPos2OSXScreenPos: NSMakePoint(x, y)]];
+ if( ! [mWin isKindOfClass:[NewtMacWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtMacWindow %p", mWin);
+ return;
+ }
+ NewtView* nView = (NewtView *) [mWin contentView];
+ if( ! [nView isKindOfClass:[NewtView class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtView %p", nView);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]];
+ [pool release];
}
diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c
index 3713cfd6c..231d6182f 100644
--- a/src/newt/native/NewtCommon.c
+++ b/src/newt/native/NewtCommon.c
@@ -1,20 +1,47 @@
#include "NewtCommon.h"
+#include <string.h>
static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException";
static jclass runtimeExceptionClz=NULL;
+static JavaVM *_jvmHandle = NULL;
+static int _jvmVersion = 0;
+
+void NewtCommon_init(JNIEnv *env) {
+ if(NULL==_jvmHandle) {
+ if(0 != (*env)->GetJavaVM(env, &_jvmHandle)) {
+ NewtCommon_FatalError(env, "NEWT: Can't fetch JavaVM handle");
+ } else {
+ _jvmVersion = (*env)->GetVersion(env);
+ }
+ jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "NEWT: Can't find %s", ClazzNameRuntimeException);
+ }
+ runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==runtimeExceptionClz) {
+ NewtCommon_FatalError(env, "NEWT: Can't use %s", ClazzNameRuntimeException);
+ }
+ }
+}
+
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
- fprintf(stderr, "%s\n", buffer);
- (*env)->FatalError(env, buffer);
+ fprintf(stderr, "%s\n", buffer);
+ if(NULL != env) {
+ (*env)->FatalError(env, buffer);
+ }
+ }
}
void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
@@ -22,61 +49,94 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
char buffer[512];
va_list ap;
- va_start(ap, msg);
- vsnprintf(buffer, sizeof(buffer), msg, ap);
- va_end(ap);
+ if(NULL==_jvmHandle) {
+ NewtCommon_FatalError(env, "NEWT: NULL JVM handle, call NewtCommon_init 1st\n");
+ return;
+ }
- (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
-}
+ if( NULL != msg ) {
+ va_start(ap, msg);
+ vsnprintf(buffer, sizeof(buffer), msg, ap);
+ va_end(ap);
-void NewtCommon_init(JNIEnv *env) {
- if(NULL==runtimeExceptionClz) {
- jclass c = (*env)->FindClass(env, ClazzNameRuntimeException);
- if(NULL==c) {
- NewtCommon_FatalError(env, "NEWT: can't find %s", ClazzNameRuntimeException);
+ if(NULL != env) {
+ (*env)->ThrowNew(env, runtimeExceptionClz, buffer);
}
- runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c);
- (*env)->DeleteLocalRef(env, c);
- if(NULL==runtimeExceptionClz) {
- NewtCommon_FatalError(env, "NEWT: can't use %s", ClazzNameRuntimeException);
+ }
+}
+
+const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText) {
+ if(NULL != jniEnv && NULL != clazz && NULL != jGetStrID) {
+ jstring jstr = (jstring) (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, jGetStrID);
+ if(NULL != jstr) {
+ const char * str = (*jniEnv)->GetStringUTFChars(jniEnv, jstr, NULL);
+ if( NULL != str) {
+ strncpy(dest, str, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, str);
+ return dest;
+ }
}
}
+ strncpy(dest, altText, destSize-1);
+ dest[destSize-1] = 0; // EOS
+ return dest;
}
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str)
{
jchar* strChars = NULL;
- strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
- if (strChars != NULL) {
- (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ if( NULL != env && 0 != str ) {
+ strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar));
+ if (strChars != NULL) {
+ (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars);
+ }
}
return strChars;
}
-JNIEnv* NewtCommon_GetJNIEnv(JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached) {
+JNIEnv* NewtCommon_GetJNIEnv(int asDaemon, int * shallBeDetached) {
JNIEnv* curEnv = NULL;
JNIEnv* newEnv = NULL;
int envRes;
+ if(NULL==_jvmHandle) {
+ fprintf(stderr, "NEWT GetJNIEnv: NULL JVM handle, call NewtCommon_init 1st\n");
+ return NULL;
+ }
+
// retrieve this thread's JNIEnv curEnv - or detect it's detached
- envRes = (*jvmHandle)->GetEnv(jvmHandle, (void **) &curEnv, jvmVersion) ;
+ envRes = (*_jvmHandle)->GetEnv(_jvmHandle, (void **) &curEnv, _jvmVersion) ;
if( JNI_EDETACHED == envRes ) {
// detached thread - attach to JVM
- if( JNI_OK != ( envRes = (*jvmHandle)->AttachCurrentThread(jvmHandle, (void**) &newEnv, NULL) ) ) {
- fprintf(stderr, "JNIEnv: can't attach thread: %d\n", envRes);
+ if( asDaemon ) {
+ envRes = (*_jvmHandle)->AttachCurrentThreadAsDaemon(_jvmHandle, (void**) &newEnv, NULL);
+ } else {
+ envRes = (*_jvmHandle)->AttachCurrentThread(_jvmHandle, (void**) &newEnv, NULL);
+ }
+ if( JNI_OK != envRes ) {
+ fprintf(stderr, "NEWT GetJNIEnv: Can't attach thread: %d\n", envRes);
return NULL;
}
curEnv = newEnv;
} else if( JNI_OK != envRes ) {
// oops ..
- fprintf(stderr, "can't GetEnv: %d\n", envRes);
+ fprintf(stderr, "NEWT GetJNIEnv: Can't GetEnv: %d\n", envRes);
return NULL;
}
if (curEnv==NULL) {
- fprintf(stderr, "env is NULL\n");
+ fprintf(stderr, "NEWT GetJNIEnv: env is NULL\n");
return NULL;
}
*shallBeDetached = NULL != newEnv;
return curEnv;
}
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached) {
+ if(NULL == _jvmHandle) {
+ fprintf(stderr, "NEWT ReleaseJNIEnv: No JavaVM handle registered, call NewtCommon_init(..) 1st");
+ } else if(shallBeDetached) {
+ (*_jvmHandle)->DetachCurrentThread(_jvmHandle);
+ }
+}
+
diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h
index f5ca73b74..43db72b5b 100644
--- a/src/newt/native/NewtCommon.h
+++ b/src/newt/native/NewtCommon.h
@@ -34,6 +34,7 @@
void NewtCommon_init(JNIEnv *env);
+const char * NewtCommon_GetStaticStringMethod(JNIEnv *jniEnv, jclass clazz, jmethodID jGetStrID, char *dest, int destSize, const char *altText);
jchar* NewtCommon_GetNullTerminatedStringChars(JNIEnv* env, jstring str);
void NewtCommon_FatalError(JNIEnv *env, const char* msg, ...);
@@ -41,23 +42,18 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
/**
*
- * 1) Store jvmHandle and jvmVersion
+ * 1) Init static jvmHandle, jvmVersion and clazz references
+ * from an early initialization call w/ valid 'JNIEnv * env'
- JavaVM *jvmHandle = NULL;
- int jvmVersion = 0;
-
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- } else {
- jvmVersion = (*env)->GetVersion(env);
- }
+ NewtCommon_init(env);
*
* 2) Use current thread JNIEnv or attach current thread to JVM, generating new JNIEnv
*
+ int asDaemon = 0;
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(asDaemon, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -69,12 +65,13 @@ void NewtCommon_throwNewRuntimeException(JNIEnv *env, const char* msg, ...);
.. your JNIEnv code here ..
*
- * 4) Detach thread from JVM, if required
+ * 4) Detach thread from JVM if required, i.e. not attached as daemon!
+ * Not recommended for recurring _daemon_ threads (performance)
*
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
*/
-JNIEnv* NewtCommon_GetJNIEnv (JavaVM * jvmHandle, int jvmVersion, int * shallBeDetached);
+JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached);
+
+void NewtCommon_ReleaseJNIEnv (int shallBeDetached);
#endif
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index c0912ad3c..8f6362ac2 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -41,53 +41,51 @@
// #define VERBOSE_ON 1
#ifdef VERBOSE_ON
- #define DBG_PRINT(...) NSLog(@ __VA_ARGS__)
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr)
// #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
#else
#define DBG_PRINT(...)
#endif
+// #define DBG_LIFECYCLE 1
+
@interface NewtView : NSView
{
jobject javaWindowObject;
- // This is set while messages are being dispatched and cleared afterward
- JavaVM *jvmHandle;
- int jvmVersion;
-
volatile BOOL destroyNotifySent;
- volatile BOOL softLocked;
+ volatile int softLockCount;
pthread_mutex_t softLockSync;
- NSTrackingRectTag ptrTrackingTag;
+ volatile NSTrackingRectTag ptrTrackingTag;
NSRect ptrRect;
NSCursor * myCursor;
+ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command
+
+ BOOL mouseConfined;
+ BOOL mouseInside;
+ BOOL mouseVisible;
+ BOOL cursorIsHidden;
+ NSPoint lastInsideMousePosition;
}
- (id)initWithFrame:(NSRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-/* Set during event dispatching cycle */
-- (void) setJVMHandle: (JavaVM*) vm;
-- (JavaVM*) getJVMHandle;
-- (void) setJVMVersion: (int) ver;
-- (int) getJVMVersion;
-
/* Register or deregister (NULL) the java Window object,
ie, if NULL, no events are send */
- (void) setJavaWindowObject: (jobject) javaWindowObj;
- (jobject) getJavaWindowObject;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) resetCursorRects;
-- (NSCursor *) cursor;
-
- (void) setDestroyNotifySent: (BOOL) v;
- (BOOL) getDestroyNotifySent;
- (BOOL) softLock;
-- (void) softUnlock;
+- (BOOL) softUnlock;
- (BOOL) needsDisplay;
- (void) displayIfNeeded;
@@ -96,6 +94,41 @@
- (void) viewDidHide;
- (void) viewDidUnhide;
- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+
+- (void) removeCursorRects;
+- (void) addCursorRects;
+- (void) removeMyCursor;
+- (void) resetCursorRects;
+- (void) setPointerIcon: (NSCursor*)c;
+- (void) mouseEntered: (NSEvent*) theEvent;
+- (void) mouseExited: (NSEvent*) theEvent;
+- (BOOL) updateMouseInside;
+- (void) cursorHide:(BOOL)v enter:(int)enterState;
+- (void) setPointerIcon:(NSCursor*)c;
+- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
+- (BOOL) isMouseVisible;
+- (void) setMouseConfined:(BOOL)v;
+- (void) setMousePosition:(NSPoint)p;
+- (void) mouseMoved: (NSEvent*) theEvent;
+- (void) scrollWheel: (NSEvent*) theEvent;
+- (void) mouseDown: (NSEvent*) theEvent;
+- (void) mouseDragged: (NSEvent*) theEvent;
+- (void) mouseUp: (NSEvent*) theEvent;
+- (void) rightMouseDown: (NSEvent*) theEvent;
+- (void) rightMouseDragged: (NSEvent*) theEvent;
+- (void) rightMouseUp: (NSEvent*) theEvent;
+- (void) otherMouseDown: (NSEvent*) theEvent;
+- (void) otherMouseDragged: (NSEvent*) theEvent;
+- (void) otherMouseUp: (NSEvent*) theEvent;
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType;
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
+
+- (void) handleFlagsChanged:(NSUInteger) mods;
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods;
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType;
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType;
@end
@@ -105,14 +138,12 @@
@interface NewtMacWindow : NSWindow
#endif
{
- BOOL isFullscreenWindow;
- BOOL mouseConfined;
- BOOL mouseVisible;
- BOOL mouseInside;
- BOOL cursorIsHidden;
BOOL realized;
- NSPoint lastInsideMousePosition;
@public
+ BOOL hasPresentationSwitch;
+ NSUInteger defaultPresentationOptions;
+ NSUInteger fullscreenPresentationOptions;
+ BOOL isFullscreenWindow;
int cachedInsets[4]; // l, r, t, b
}
@@ -122,32 +153,31 @@
styleMask: (NSUInteger) windowStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
- (void) release;
+#endif
- (void) dealloc;
-- (void) setUnrealized;
+- (void) setRealized: (BOOL)v;
- (BOOL) isRealized;
-- (void) updateInsets: (JNIEnv*) env;
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
- (void) attachToParent: (NSWindow*) parent;
- (void) detachFromParent: (NSWindow*) parent;
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p;
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz;
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p;
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz;
- (NSPoint) getLocationOnScreen: (NSPoint) p;
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
-
-- (BOOL) isMouseInside;
-- (void) cursorHide:(BOOL)v;
-- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
-- (void) setMouseConfined:(BOOL)v;
-- (void) setMousePosition:(NSPoint)p;
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType;
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType;
- (void) focusChanged: (BOOL) gained;
+- (void) keyDown: (NSEvent*) theEvent;
+- (void) keyUp: (NSEvent*) theEvent;
+- (void) flagsChanged: (NSEvent *) theEvent;
+- (BOOL) acceptsMouseMovedEvents;
+- (BOOL) acceptsFirstResponder;
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
- (BOOL) canBecomeKeyWindow;
@@ -155,20 +185,7 @@
- (void) resignKeyWindow;
- (void) windowDidBecomeKey: (NSNotification *) notification;
- (void) windowDidResignKey: (NSNotification *) notification;
-- (void) keyDown: (NSEvent*) theEvent;
-- (void) keyUp: (NSEvent*) theEvent;
-- (void) mouseEntered: (NSEvent*) theEvent;
-- (void) mouseExited: (NSEvent*) theEvent;
-- (void) mouseMoved: (NSEvent*) theEvent;
-- (void) scrollWheel: (NSEvent*) theEvent;
-- (void) mouseDown: (NSEvent*) theEvent;
-- (void) mouseDragged: (NSEvent*) theEvent;
-- (void) mouseUp: (NSEvent*) theEvent;
-- (void) rightMouseDown: (NSEvent*) theEvent;
-- (void) rightMouseDragged: (NSEvent*) theEvent;
-- (void) rightMouseUp: (NSEvent*) theEvent;
-- (void) otherMouseDown: (NSEvent*) theEvent;
-- (void) otherMouseUp: (NSEvent*) theEvent;
+
- (void) windowDidResize: (NSNotification*) notification;
- (void) windowDidMove: (NSNotification*) notification;
- (BOOL) windowClosingImpl: (BOOL) force;
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index f914467af..b4133ac7e 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -36,42 +36,140 @@
#import "KeyEvent.h"
#import "MouseEvent.h"
-jint GetDeltaY(NSEvent *event, jint javaMods) {
- CGFloat deltaY = 0.0;
+#include <CoreFoundation/CoreFoundation.h>
+#include <Carbon/Carbon.h> /* For kVK_ constants, and TIS functions. */
+
+#include <math.h>
+
+#define PRINTF(...) NSLog(@ __VA_ARGS__)
+
+static jfloat GetDelta(NSEvent *event, jint javaMods[]) {
CGEventRef cgEvent = [event CGEvent];
+ CGFloat deltaY = 0.0;
+ CGFloat deltaX = 0.0;
+ CGFloat delta = 0.0;
if (CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventIsContinuous)) {
// mouse pad case
- deltaY =
- CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
- // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY);
+ deltaX = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis2);
+ deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1);
+ // fprintf(stderr, "WHEEL/PAD: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if( fabsf(deltaX) > fabsf(deltaY) ) {
+ javaMods[0] |= EVENT_SHIFT_MASK;
+ delta = deltaX;
+ } else {
+ delta = deltaY;
+ }
} else {
// traditional mouse wheel case
+ deltaX = [event deltaX];
deltaY = [event deltaY];
- // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY);
- if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) {
+ // fprintf(stderr, "WHEEL/TRACK: %lf/%lf - 0x%X\n", (double)deltaX, (double)deltaY, javaMods[0]);
+ if (deltaY == 0.0 && (javaMods[0] & EVENT_SHIFT_MASK) != 0) {
// shift+vertical wheel scroll produces horizontal scroll
// we convert it to vertical
- deltaY = [event deltaX];
+ delta = deltaX;
+ } else {
+ delta = deltaY;
}
- if (-1.0 < deltaY && deltaY < 1.0) {
- deltaY *= 10.0;
+ if (-1.0 < delta && delta < 1.0) {
+ delta *= 10.0;
} else {
- if (deltaY < 0.0) {
- deltaY = deltaY - 0.5f;
+ if (delta < 0.0) {
+ delta = delta - 0.5f;
} else {
- deltaY = deltaY + 0.5f;
+ delta = delta + 0.5f;
+ }
+ }
+ }
+ // fprintf(stderr, "WHEEL/RES: %lf - 0x%X\n", (double)delta, javaMods[0]);
+ return (jfloat) delta;
+}
+
+#define kVK_Shift 0x38
+#define kVK_Option 0x3A
+#define kVK_Control 0x3B
+#define kVK_Command 0x37
+
+static jint mods2JavaMods(NSUInteger mods)
+{
+ int javaMods = 0;
+ if (mods & NSShiftKeyMask) {
+ javaMods |= EVENT_SHIFT_MASK;
+ }
+ if (mods & NSControlKeyMask) {
+ javaMods |= EVENT_CTRL_MASK;
+ }
+ if (mods & NSCommandKeyMask) {
+ javaMods |= EVENT_META_MASK;
+ }
+ if (mods & NSAlternateKeyMask) {
+ javaMods |= EVENT_ALT_MASK;
+ }
+ return javaMods;
+}
+
+static CFStringRef CKCH_CreateStringForKey(CGKeyCode keyCode, const UCKeyboardLayout *keyboardLayout) {
+ UInt32 keysDown = 0;
+ UniChar chars[4];
+ UniCharCount realLength;
+
+ UCKeyTranslate(keyboardLayout, keyCode,
+ kUCKeyActionDisplay, 0,
+ LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit,
+ &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars);
+
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
+}
+
+static CFMutableDictionaryRef CKCH_CreateCodeToCharDict(TISInputSourceRef keyboard) {
+ CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData);
+ const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+
+ CFMutableDictionaryRef codeToCharDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, NULL, NULL);
+ if ( NULL != codeToCharDict ) {
+ intptr_t i;
+ for (i = 0; i < 128; ++i) {
+ CFStringRef string = CKCH_CreateStringForKey((CGKeyCode)i, keyboardLayout);
+ if( NULL != string ) {
+ CFIndex stringLen = CFStringGetLength (string);
+ if ( 0 < stringLen ) {
+ UniChar character = CFStringGetCharacterAtIndex(string, 0);
+ DBG_PRINT("CKCH: MAP 0x%X -> %c\n", (int)i, character);
+ CFDictionaryAddValue(codeToCharDict, (const void *)i, (const void *)(intptr_t)character);
+ }
+ CFRelease(string);
}
}
}
- // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY);
- return (jint) deltaY;
+ return codeToCharDict;
+}
+
+static CFMutableDictionaryRef CKCH_USCodeToNNChar = NULL;
+
+static void CKCH_CreateDictionaries() {
+ TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+ CKCH_USCodeToNNChar = CKCH_CreateCodeToCharDict(currentKeyboard);
+ CFRelease(currentKeyboard);
+}
+
+static UniChar CKCH_CharForKeyCode(jshort keyCode) {
+ UniChar rChar = 0;
+
+ if ( NULL != CKCH_USCodeToNNChar ) {
+ intptr_t code = (intptr_t) keyCode;
+ intptr_t character = 0;
+
+ if ( CFDictionaryGetValueIfPresent(CKCH_USCodeToNNChar, (void *)code, (const void **)&character) ) {
+ rChar = (UniChar) character;
+ DBG_PRINT("CKCH: OK 0x%X -> 0x%X\n", (int)keyCode, (int)rChar);
+ }
+ }
+ return rChar;
}
static jmethodID enqueueMouseEventID = NULL;
-static jmethodID sendMouseEventID = NULL;
static jmethodID enqueueKeyEventID = NULL;
-static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
static jmethodID insetsChangedID = NULL;
@@ -82,24 +180,21 @@ static jmethodID focusChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-// Can't use USE_SENDIO_DIRECT, ie w/o enqueueing to EDT,
+// Need to enqueue all events to EDT,
// since we may operate on AWT-AppKit (Main Thread)
// and direct issuing 'requestFocus()' would deadlock:
// AWT-AppKit
// AWT-EventQueue-0
-//
-// #define USE_SENDIO_DIRECT 1
@implementation NewtView
- (id)initWithFrame:(NSRect)frameRect
{
+ id res = [super initWithFrame:frameRect];
javaWindowObject = NULL;
- jvmHandle = NULL;
- jvmVersion = 0;
destroyNotifySent = NO;
- softLocked = NO;
+ softLockCount = 0;
pthread_mutexattr_t softLockSyncAttr;
pthread_mutexattr_init(&softLockSyncAttr);
@@ -107,59 +202,46 @@ static jmethodID windowRepaintID = NULL;
pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive
ptrTrackingTag = 0;
-
- /**
- NSCursor crs = [NSCursor arrowCursor];
- NSImage crsImg = [crs image];
- NSPoint crsHot = [crs hotSpot];
- myCursor = [[NSCursor alloc] initWithImage: crsImg hotSpot:crsHot];
- */
myCursor = NULL;
- return [super initWithFrame:frameRect];
+ modsDown[0] = NO; // shift
+ modsDown[1] = NO; // ctrl
+ modsDown[2] = NO; // alt
+ modsDown[3] = NO; // win
+ mouseConfined = NO;
+ mouseVisible = YES;
+ mouseInside = NO;
+ cursorIsHidden = NO;
+
+ DBG_PRINT("NewtView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+ return res;
}
+#ifdef DBG_LIFECYCLE
- (void) release
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
[super release];
}
+#endif
- (void) dealloc
{
- if(softLocked) {
+ DBG_PRINT("NewtView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+ if( 0 < softLockCount ) {
NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n");
}
+ [self removeCursorRects];
+ [self removeMyCursor];
+
pthread_mutex_destroy(&softLockSync);
-#ifdef VERBOSE_ON
- NSLog(@"NewtView::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
+ DBG_PRINT("NewtView::dealloc.X: %p\n", self);
[super dealloc];
}
-- (void) setJVMHandle: (JavaVM*) vm
-{
- jvmHandle = vm;
-}
-- (JavaVM*) getJVMHandle
-{
- return jvmHandle;
-}
-
-- (void) setJVMVersion: (int) ver
-{
- jvmVersion = ver;
-}
-
-- (int) getJVMVersion
-{
- return jvmVersion;
-}
-
- (void) setJavaWindowObject: (jobject) javaWindowObj
{
javaWindowObject = javaWindowObj;
@@ -170,32 +252,6 @@ static jmethodID windowRepaintID = NULL;
return javaWindowObject;
}
-- (void) rightMouseDown: (NSEvent*) theEvent
-{
- NSResponder* next = [self nextResponder];
- if (next != nil) {
- [next rightMouseDown: theEvent];
- }
-}
-
-- (void) resetCursorRects
-{
- [super resetCursorRects];
-
- if(0 != ptrTrackingTag) {
- // [self removeCursorRect: ptrRect cursor: myCursor];
- [self removeTrackingRect: ptrTrackingTag];
- }
- ptrRect = [self bounds];
- // [self addCursorRect: ptrRect cursor: myCursor];
- ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
-}
-
-- (NSCursor *) cursor
-{
- return myCursor;
-}
-
- (void) setDestroyNotifySent: (BOOL) v
{
destroyNotifySent = v;
@@ -209,18 +265,27 @@ static jmethodID windowRepaintID = NULL;
- (BOOL) softLock
{
// DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self());
- // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]);
- pthread_mutex_lock(&softLockSync);
- softLocked = YES;
+ int err;
+ if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) {
+ NSLog(@"NewtView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ softLockCount++;
// DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self());
- return softLocked;
+ return 0 < softLockCount;
}
-- (void) softUnlock
+- (BOOL) softUnlock
{
// DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
- softLocked = NO;
- pthread_mutex_unlock(&softLockSync);
+ softLockCount--;
+ int err;
+ if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+ softLockCount++;
+ NSLog(@"NewtView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ return YES;
}
- (BOOL) needsDisplay
@@ -256,7 +321,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("drawRect: null JNIEnv\n");
return;
@@ -268,9 +333,8 @@ static jmethodID windowRepaintID = NULL;
dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y,
dirtyRect.size.width, dirtyRect.size.height);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void) viewDidHide
@@ -280,7 +344,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidHide: null JNIEnv\n");
return;
@@ -288,9 +352,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_FALSE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidHide];
}
@@ -302,7 +365,7 @@ static jmethodID windowRepaintID = NULL;
return;
}
int shallBeDetached = 0;
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("viewDidUnhide: null JNIEnv\n");
return;
@@ -310,9 +373,8 @@ static jmethodID windowRepaintID = NULL;
(*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, JNI_TRUE);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
[super viewDidUnhide];
}
@@ -322,232 +384,140 @@ static jmethodID windowRepaintID = NULL;
return YES;
}
-@end
-
-@implementation NewtMacWindow
-
-+ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+- (BOOL) becomeFirstResponder
{
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
- sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
- visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
- insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
- positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
- focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
- windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
- windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
- if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
- positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
- {
- return YES;
- }
- return NO;
+ DBG_PRINT( "*************** View.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (id) initWithContentRect: (NSRect) contentRect
- styleMask: (NSUInteger) windowStyle
- backing: (NSBackingStoreType) bufferingType
- defer: (BOOL) deferCreation
- screen:(NSScreen *)screen
- isFullscreenWindow:(BOOL)isfs
+- (BOOL) resignFirstResponder
{
- id res = [super initWithContentRect: contentRect
- styleMask: windowStyle
- backing: bufferingType
- defer: deferCreation
- screen: screen];
- isFullscreenWindow = isfs;
- // Why is this necessary? Without it we don't get any of the
- // delegate methods like resizing and window movement.
- [self setDelegate: self];
- cachedInsets[0] = 0; // l
- cachedInsets[1] = 0; // r
- cachedInsets[2] = 0; // t
- cachedInsets[3] = 0; // b
- mouseConfined = NO;
- mouseVisible = YES;
- mouseInside = NO;
- cursorIsHidden = NO;
- realized = YES;
- return res;
+ DBG_PRINT( "*************** View.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) release
+- (void) removeCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::release\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super release];
+ if(0 != ptrTrackingTag) {
+ if(NULL != myCursor) {
+ [self removeCursorRect: ptrRect cursor: myCursor];
+ }
+ [self removeTrackingRect: ptrTrackingTag];
+ ptrTrackingTag = 0;
+ }
}
-- (void) dealloc
+- (void) addCursorRects
{
-#ifdef VERBOSE_ON
- NSLog(@"NewtWindow::dealloc\n");
- NSLog(@"%@",[NSThread callStackSymbols]);
-#endif
- [super dealloc];
+ ptrRect = [self bounds];
+ if(NULL != myCursor) {
+ [self addCursorRect: ptrRect cursor: myCursor];
+ }
+ ptrTrackingTag = [self addTrackingRect: ptrRect owner: self userData: nil assumeInside: NO];
}
-- (void) setUnrealized
+- (void) removeMyCursor
{
- realized = NO;
+ if(NULL != myCursor) {
+ [myCursor release];
+ myCursor = NULL;
+ }
}
-- (BOOL) isRealized
+- (void) resetCursorRects
{
- return realized;
+ [super resetCursorRects];
+
+ [self removeCursorRects];
+ [self addCursorRects];
}
-- (void) updateInsets: (JNIEnv*) env
+- (void) setPointerIcon: (NSCursor*)c
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ DBG_PRINT( "setPointerIcon: %p -> %p, top %p, mouseInside %d\n", myCursor, c, [NSCursor currentCursor], (int)mouseInside);
+ if( c != myCursor ) {
+ [self removeCursorRects];
+ [self removeMyCursor];
+ myCursor = c;
+ if( NULL != myCursor ) {
+ [myCursor retain];
+ }
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (env==NULL || javaWindowObject == NULL) {
- return;
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin invalidateCursorRectsForView: self];
}
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- // note: this is a simplistic implementation which doesn't take
- // into account DPI and scaling factor
- CGFloat l = contentRect.origin.x - frameRect.origin.x;
- cachedInsets[0] = (int)l; // l
- cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
- cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
- cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
-
- DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
-
- (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
}
-- (void) attachToParent: (NSWindow*) parent
-{
- DBG_PRINT( "attachToParent.1\n");
- [parent addChildWindow: self ordered: NSWindowAbove];
- DBG_PRINT( "attachToParent.2\n");
- [self setParentWindow: parent];
- DBG_PRINT( "attachToParent.X\n");
-}
-
-- (void) detachFromParent: (NSWindow*) parent
+- (void) mouseEntered: (NSEvent*) theEvent
{
- DBG_PRINT( "detachFromParent.1\n");
- [self setParentWindow: nil];
- if(NULL != parent) {
- DBG_PRINT( "detachFromParent.2\n");
- [parent removeChildWindow: self];
+ DBG_PRINT( "mouseEntered: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ mouseInside = YES;
+ [self cursorHide: !mouseVisible enter: 1];
+ if(NO == mouseConfined) {
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ }
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ [nsWin makeFirstResponder: self];
}
- DBG_PRINT( "detachFromParent.X\n");
-}
-
-/**
- * p abs screen position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtScreenWinPos2OSXScreenPos: (NSPoint) p
-{
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
- int totalHeight = mViewFrame.size.height + cachedInsets[2] + cachedInsets[3]; // height + insets[top+bottom]
-
- NSScreen* screen = [self screen];
- NSRect screenFrame = [screen frame];
-
- return NSMakePoint(screenFrame.origin.x + p.x + cachedInsets[0],
- screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
-}
-
-/**
- * p rel client window position w/ top-left origin
- * returns: abs screen position w/ bottom-left origin
- */
-- (NSPoint) newtClientWinPos2OSXScreenPos: (NSPoint) p
-{
- NSRect winFrame = [self frame];
-
- NSView* mView = [self contentView];
- NSRect mViewFrame = [mView frame];
-
- return NSMakePoint(winFrame.origin.x + p.x,
- winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
}
-/**
- * y-flips input / output
- * p rel client window position w/ top-left origin
- * returns: location in 0/0 top-left space.
- */
-- (NSPoint) getLocationOnScreen: (NSPoint) p
+- (void) mouseExited: (NSEvent*) theEvent
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
-
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
-
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = viewFrame.size.height - p.y; // y-flip
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectToScreen: r]; // 10.7
- NSPoint oS = [self convertBaseToScreen: r.origin];
- oS.y = screenRect.origin.y + screenRect.size.height - oS.y;
- return oS;
+ DBG_PRINT( "mouseExited: confined %d, visible %d, PointerIcon %p, top %p\n", mouseConfined, mouseVisible, myCursor, [NSCursor currentCursor]);
+ if(NO == mouseConfined) {
+ mouseInside = NO;
+ [self cursorHide: NO enter: -1];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
+ [self resignFirstResponder];
+ } else {
+ [self setMousePosition: lastInsideMousePosition];
+ }
}
-- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
+- (void) setMousePosition:(NSPoint)p
{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ NSWindow* nsWin = [self window];
+ if( NULL != nsWin ) {
+ NSScreen* screen = [nsWin screen];
+ NSRect screenRect = [screen frame];
- NSRect r;
- r.origin.x = p.x;
- r.origin.y = p.y;
- r.size.width = 0;
- r.size.height = 0;
- // NSRect rS = [win convertRectFromScreen: r]; // 10.7
- NSPoint oS = [self convertScreenToBase: r.origin];
- oS.y = viewFrame.size.height - oS.y; // y-flip
- return oS;
+ CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
+ CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
+ CGEventPost (kCGHIDEventTap, ev);
+ }
}
-- (BOOL) isMouseInside
+- (BOOL) updateMouseInside
{
- NSView* view = [self contentView];
- NSRect viewFrame = [view frame];
+ NSRect viewFrame = [self frame];
NSPoint l1 = [NSEvent mouseLocation];
NSPoint l0 = [self screenPos2NewtClientWinPos: l1];
- return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
- viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ mouseInside = viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
+ viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+ return mouseInside;
}
- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus
{
mouseVisible = v;
- mouseInside = [self isMouseInside];
+ [self updateMouseInside];
DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n",
mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus);
if(YES == focus && YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ [self cursorHide: !mouseVisible enter: 0];
}
}
+- (BOOL) isMouseVisible
+{
+ return mouseVisible;
+}
-- (void) cursorHide:(BOOL)v
+- (void) cursorHide:(BOOL)v enter:(int)enterState
{
- DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v);
+ DBG_PRINT( "cursorHide: %d -> %d, enter %d; PointerIcon: %p, top %p\n",
+ cursorIsHidden, v, enterState, myCursor, [NSCursor currentCursor]);
if(v) {
if(!cursorIsHidden) {
[NSCursor hide];
@@ -567,108 +537,105 @@ static jmethodID windowRepaintID = NULL;
DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible);
}
-- (void) setMousePosition:(NSPoint)p
+- (void) mouseMoved: (NSEvent*) theEvent
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ if( mouseInside ) {
+ NSCursor * currentCursor = [NSCursor currentCursor];
+ BOOL setCursor = NULL != myCursor && NO == cursorIsHidden && currentCursor != myCursor;
+ DBG_PRINT( "mouseMoved.set: %d; mouseInside %d, CursorHidden %d, PointerIcon: %p, top %p\n",
+ setCursor, mouseInside, cursorIsHidden, myCursor, currentCursor);
+ if( setCursor ) {
+ // FIXME: Workaround missing NSCursor update for 'fast moving' pointer
+ [myCursor set];
+ }
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ }
+}
- CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
- CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
- CGEventPost (kCGHIDEventTap, ev);
+- (void) scrollWheel: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
}
-static jint mods2JavaMods(NSUInteger mods)
+- (void) mouseDown: (NSEvent*) theEvent
{
- int javaMods = 0;
- if (mods & NSShiftKeyMask) {
- javaMods |= EVENT_SHIFT_MASK;
- }
- if (mods & NSControlKeyMask) {
- javaMods |= EVENT_CTRL_MASK;
- }
- if (mods & NSCommandKeyMask) {
- javaMods |= EVENT_META_MASK;
- }
- if (mods & NSAlternateKeyMask) {
- javaMods |= EVENT_ALT_MASK;
- }
- return javaMods;
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
}
-- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType
+- (void) mouseDragged: (NSEvent*) theEvent
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
- return;
- }
- int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
- DBG_PRINT("sendKeyEvent: null JNIEnv\n");
- return;
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
+
+- (void) mouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
+
+- (void) rightMouseDown: (NSEvent*) theEvent
+{
+ NSResponder* next = [self nextResponder];
+ if (next != nil) {
+ [next rightMouseDown: theEvent];
}
+ // FIXME: ^^ OR [super rightMouseDown: theEvent] ?
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- int i;
- jint keyCode = (jint) [event keyCode];
- NSString* chars = [event charactersIgnoringModifiers];
- int len = [chars length];
- jint javaMods = mods2JavaMods([event modifierFlags]);
+- (void) rightMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- for (i = 0; i < len; i++) {
- // Note: the key code in the NSEvent does not map to anything we can use
- jchar keyChar = (jchar) [chars characterAtIndex: i];
+- (void) rightMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+}
- DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode);
+- (void) otherMouseDown: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+}
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID,
- evType, javaMods, keyCode, keyChar);
- #else
- (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
- evType, javaMods, keyCode, keyChar);
- #endif
- }
+- (void) otherMouseDragged: (NSEvent*) theEvent
+{
+ lastInsideMousePosition = [NSEvent mouseLocation];
+ // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+- (void) otherMouseUp: (NSEvent*) theEvent
+{
+ [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
}
-- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jshort) evType
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("sendMouseEvent: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("sendMouseEvent: null JNIEnv\n");
return;
}
- jint javaMods = mods2JavaMods([event modifierFlags]);
+ jint javaMods[] = { 0 } ;
+ javaMods[0] = mods2JavaMods([event modifierFlags]);
// convert to 1-based button number (or use zero if no button is involved)
// TODO: detect mouse button when mouse wheel scrolled
- jint javaButtonNum = 0;
- jint scrollDeltaY = 0;
+ jshort javaButtonNum = 0;
+ jfloat scrollDeltaY = 0.0f;
switch ([event type]) {
case NSScrollWheel: {
- scrollDeltaY = GetDeltaY(event, javaMods);
+ scrollDeltaY = GetDelta(event, javaMods);
javaButtonNum = 1;
break;
}
@@ -699,246 +666,484 @@ static jint mods2JavaMods(NSUInteger mods)
NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]];
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID,
- evType, javaMods,
- (jint) location.x, (jint) location.y,
- javaButtonNum, scrollDeltaY);
- #else
(*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE,
- evType, javaMods,
+ evType, javaMods[0],
(jint) location.x, (jint) location.y,
javaButtonNum, scrollDeltaY);
- #endif
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
-- (void) focusChanged: (BOOL) gained
+- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p
{
- DBG_PRINT( "focusChanged: gained %d\n", gained);
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ NSRect viewFrame = [self frame];
+
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = p.y;
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [[self window] convertRectFromScreen: r]; // 10.7
+ NSPoint oS = [[self window] convertScreenToBase: r.origin];
+ oS.y = viewFrame.size.height - oS.y; // y-flip
+ return oS;
+}
+
+- (void) handleFlagsChanged:(NSUInteger) mods
+{
+ [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods];
+ [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods];
+ [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods];
+ [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods];
+}
+
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods
+{
+ if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) {
+ modsDown[keyIdx] = YES;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED];
+ } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) {
+ modsDown[keyIdx] = NO;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED];
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+}
+
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jshort) evType
+{
+ jshort keyCode = (jshort) [event keyCode];
+ NSString* chars = [event charactersIgnoringModifiers];
+ NSUInteger mods = [event modifierFlags];
+ [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType];
+}
+
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType
+{
if (javaWindowObject == NULL) {
- DBG_PRINT("focusChanged: null javaWindowObject\n");
+ DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("focusChanged: null JNIEnv\n");
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
return;
}
- (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+ int i;
+ int len = NULL != chars ? [chars length] : 0;
+ jint javaMods = mods2JavaMods(mods);
+
+ if(len > 0) {
+ // printable chars
+ for (i = 0; i < len; i++) {
+ // Note: the key code in the NSEvent does not map to anything we can use
+ UniChar keyChar = (UniChar) [chars characterAtIndex: i];
+ UniChar keySymChar = CKCH_CharForKeyCode(keyCode);
+
+ DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar,
+ (int)mods, (int)javaMods, (int)keySymChar);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
+ }
+ } else {
+ // non-printable chars
+ jchar keyChar = (jchar) 0;
+
+ DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, keyChar, keyChar);
}
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
-- (BOOL) becomeFirstResponder
+@end
+
+@implementation NewtMacWindow
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
{
- DBG_PRINT( "*************** becomeFirstResponder\n");
- return [super becomeFirstResponder];
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
+ requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
+ if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID &&
+ positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ {
+ CKCH_CreateDictionaries();
+ return YES;
+ }
+ return NO;
}
-- (BOOL) resignFirstResponder
+- (id) initWithContentRect: (NSRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSBackingStoreType) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs
{
- DBG_PRINT( "*************** resignFirstResponder\n");
- return [super resignFirstResponder];
+ id res = [super initWithContentRect: contentRect
+ styleMask: windowStyle
+ backing: bufferingType
+ defer: deferCreation];
+ // OSX 10.6
+ if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] &&
+ [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) {
+ hasPresentationSwitch = YES;
+ defaultPresentationOptions = [NSApp currentSystemPresentationOptions];
+ fullscreenPresentationOptions =
+ // NSApplicationPresentationDefault|
+ // NSApplicationPresentationAutoHideDock|
+ NSApplicationPresentationHideDock|
+ // NSApplicationPresentationAutoHideMenuBar|
+ NSApplicationPresentationHideMenuBar|
+ NSApplicationPresentationDisableAppleMenu|
+ // NSApplicationPresentationDisableProcessSwitching|
+ // NSApplicationPresentationDisableSessionTermination|
+ NSApplicationPresentationDisableHideApplication|
+ // NSApplicationPresentationDisableMenuBarTransparency|
+ // NSApplicationPresentationFullScreen| // OSX 10.7
+ 0 ;
+ } else {
+ hasPresentationSwitch = NO;
+ defaultPresentationOptions = 0;
+ fullscreenPresentationOptions = 0;
+ }
+
+ isFullscreenWindow = isfs;
+ // Why is this necessary? Without it we don't get any of the
+ // delegate methods like resizing and window movement.
+ [self setDelegate: self];
+ cachedInsets[0] = 0; // l
+ cachedInsets[1] = 0; // r
+ cachedInsets[2] = 0; // t
+ cachedInsets[3] = 0; // b
+ realized = YES;
+ DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n",
+ res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]);
+ return res;
}
-- (BOOL) canBecomeKeyWindow
+#ifdef DBG_LIFECYCLE
+- (void) release
{
- // Even if the window is borderless, we still want it to be able
- // to become the key window to receive keyboard events
- return YES;
+ DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"%@",[NSThread callStackSymbols]);
+ [super release];
}
+#endif
-- (void) becomeKeyWindow
+- (void) dealloc
{
- DBG_PRINT( "*************** becomeKeyWindow\n");
- [super becomeKeyWindow];
+ DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+
+ NewtView* mView = (NewtView *)[self contentView];
+ if( NULL != mView ) {
+ [mView release];
+ }
+ [super dealloc];
+ DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
}
-- (void) resignKeyWindow
+- (void) setRealized: (BOOL)v
{
- DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
- if(!isFullscreenWindow) {
- [super resignKeyWindow];
+ realized = v;
+}
+
+- (BOOL) isRealized
+{
+ return realized;
+}
+
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
+{
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ cachedInsets[0] = (int)l; // l
+ cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
+ cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
+ cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+
+ DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
}
}
-- (void) windowDidBecomeKey: (NSNotification *) notification
+- (void) attachToParent: (NSWindow*) parent
{
- DBG_PRINT( "*************** windowDidBecomeKey\n");
- mouseInside = [self isMouseInside];
- if(YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ DBG_PRINT( "attachToParent.1\n");
+ [parent addChildWindow: self ordered: NSWindowAbove];
+ DBG_PRINT( "attachToParent.2\n");
+ [self setParentWindow: parent];
+ DBG_PRINT( "attachToParent.X\n");
+}
+
+- (void) detachFromParent: (NSWindow*) parent
+{
+ DBG_PRINT( "detachFromParent.1\n");
+ [self setParentWindow: nil];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
}
- [self focusChanged: YES];
+ DBG_PRINT( "detachFromParent.X\n");
}
-- (void) windowDidResignKey: (NSNotification *) notification
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using contentView's client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- DBG_PRINT( "*************** windowDidResignKey\n");
- // Implicit mouse exit by OS X
- [self focusChanged: NO];
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+ return [self newtAbsClientTLWinPos2AbsBLScreenPos: p size: mViewFrame.size];
}
-- (void) keyDown: (NSEvent*) theEvent
+/**
+ * p abs screen position of client-area pos w/ top-left origin, using given client NSSize
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtAbsClientTLWinPos2AbsBLScreenPos: (NSPoint) p size: (NSSize) nsz
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+ int totalHeight = nsz.height + cachedInsets[3]; // height + insets.bottom
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: given %d/%d %dx%d, insets bottom %d -> totalHeight %d\n",
+ (int)p.x, (int)p.y, (int)nsz.width, (int)nsz.height, cachedInsets[3], totalHeight);
+
+ NSScreen* screen = [self screen];
+ NSRect screenFrame = [screen frame];
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: screen %d/%d %dx%d\n",
+ (int)screenFrame.origin.x, (int)screenFrame.origin.y, (int)screenFrame.size.width, (int)screenFrame.size.height);
+
+ NSPoint r = NSMakePoint(screenFrame.origin.x + p.x,
+ screenFrame.origin.y + screenFrame.size.height - p.y - totalHeight);
+
+ DBG_PRINT( "newtAbsClientTLWinPos2AbsBLScreenPos: result %d/%d\n", (int)r.x, (int)r.y);
+
+ return r;
}
-- (void) keyUp: (NSEvent*) theEvent
+/**
+ * p rel client window position w/ top-left origin
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (NSPoint) newtRelClientTLWinPos2AbsBLScreenPos: (NSPoint) p
{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
+ NSRect winFrame = [self frame];
+
+ NSView* mView = [self contentView];
+ NSRect mViewFrame = [mView frame];
+
+ return NSMakePoint(winFrame.origin.x + p.x,
+ winFrame.origin.y + ( mViewFrame.size.height - p.y ) ); // y-flip in view
}
-- (void) mouseEntered: (NSEvent*) theEvent
+- (NSSize) newtClientSize2TLSize: (NSSize) nsz
{
- DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible);
- mouseInside = YES;
- [self cursorHide: !mouseVisible];
- if(NO == mouseConfined) {
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
+ NSSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+ return topSZ;
+}
+
+/**
+ * y-flips input / output
+ * p rel client window position w/ top-left origin
+ * returns: location in 0/0 top-left space.
+ */
+- (NSPoint) getLocationOnScreen: (NSPoint) p
+{
+ NSScreen* screen = [self screen];
+ NSRect screenRect = [screen frame];
+
+ NSView* view = [self contentView];
+ NSRect viewFrame = [view frame];
+
+ NSRect r;
+ r.origin.x = p.x;
+ r.origin.y = viewFrame.size.height - p.y; // y-flip
+ r.size.width = 0;
+ r.size.height = 0;
+ // NSRect rS = [win convertRectToScreen: r]; // 10.7
+ NSPoint oS = [self convertBaseToScreen: r.origin];
+ oS.y = screenRect.origin.y + screenRect.size.height - oS.y;
+ return oS;
+}
+
+- (void) focusChanged: (BOOL) gained
+{
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
+ return;
+ }
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
}
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
-- (void) mouseExited: (NSEvent*) theEvent
+- (void) keyDown: (NSEvent*) theEvent
{
- DBG_PRINT( "mouseExited: confined %d, visible %d\n", mouseConfined, mouseVisible);
- if(NO == mouseConfined) {
- mouseInside = NO;
- [self cursorHide: NO];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED];
- } else {
- [self setMousePosition: lastInsideMousePosition];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_PRESSED];
}
}
-- (void) mouseMoved: (NSEvent*) theEvent
+- (void) keyUp: (NSEvent*) theEvent
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView sendKeyEvent: theEvent eventType: (jshort)EVENT_KEY_RELEASED];
+ }
}
-- (void) scrollWheel: (NSEvent*) theEvent
+- (void) flagsChanged:(NSEvent *) theEvent
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_WHEEL_MOVED];
+ NSUInteger mods = [theEvent modifierFlags];
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ [newtView handleFlagsChanged: mods];
+ }
}
-- (void) mouseDown: (NSEvent*) theEvent
+- (BOOL) acceptsMouseMovedEvents
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ return YES;
}
-- (void) mouseDragged: (NSEvent*) theEvent
+- (BOOL) acceptsFirstResponder
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ return YES;
}
-- (void) mouseUp: (NSEvent*) theEvent
+- (BOOL) becomeFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** Win.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
}
-- (void) rightMouseDown: (NSEvent*) theEvent
+- (BOOL) resignFirstResponder
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** Win.resignFirstResponder\n");
+ return [super resignFirstResponder];
}
-- (void) rightMouseDragged: (NSEvent*) theEvent
+- (BOOL) canBecomeKeyWindow
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
}
-- (void) rightMouseUp: (NSEvent*) theEvent
+- (void) becomeKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
}
-- (void) otherMouseDown: (NSEvent*) theEvent
+- (void) resignKeyWindow
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED];
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ if(!isFullscreenWindow) {
+ [super resignKeyWindow];
+ }
}
-- (void) otherMouseDragged: (NSEvent*) theEvent
+- (void) windowDidBecomeKey: (NSNotification *) notification
{
- lastInsideMousePosition = [NSEvent mouseLocation];
- // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED];
+ DBG_PRINT( "*************** windowDidBecomeKey\n");
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ BOOL mouseInside = [newtView updateMouseInside];
+ if(YES == mouseInside) {
+ [newtView cursorHide: ![newtView isMouseVisible] enter: 1];
+ }
+ }
+ [self focusChanged: YES];
}
-- (void) otherMouseUp: (NSEvent*) theEvent
+- (void) windowDidResignKey: (NSNotification *) notification
{
- [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED];
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ // Implicit mouse exit by OS X
+ [self focusChanged: NO];
}
- (void)windowDidResize: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("windowDidResize: null javaWindowObject\n");
- return;
- }
+ jobject javaWindowObject = NULL;
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+
+ if( NULL == env ) {
DBG_PRINT("windowDidResize: null JNIEnv\n");
return;
}
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtView class]] ) {
+ javaWindowObject = [newtView getJavaWindowObject];
+ }
+ if( NULL != javaWindowObject ) {
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: env jwin:javaWindowObject];
- // update insets on every window resize for lack of better hook place
- [self updateInsets: env];
-
- NSRect frameRect = [self frame];
- NSRect contentRect = [self contentRectForFrameRect: frameRect];
-
- (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
- (jint) contentRect.size.width,
- (jint) contentRect.size.height, JNI_FALSE);
+ NSRect frameRect = [self frame];
+ NSRect contentRect = [self contentRectForFrameRect: frameRect];
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
+ (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, JNI_FALSE,
+ (jint) contentRect.size.width,
+ (jint) contentRect.size.height, JNI_FALSE);
}
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (void)windowDidMove: (NSNotification*) notification
{
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
return;
}
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
+ jobject javaWindowObject = [newtView getJavaWindowObject];
if (javaWindowObject == NULL) {
DBG_PRINT("windowDidMove: null javaWindowObject\n");
return;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowDidMove: null JNIEnv\n");
return;
@@ -948,9 +1153,8 @@ static jint mods2JavaMods(NSUInteger mods)
p0 = [self getLocationOnScreen: p0];
(*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_FALSE, (jint) p0.x, (jint) p0.y);
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
}
- (BOOL)windowShouldClose: (id) sender
@@ -966,41 +1170,38 @@ static jint mods2JavaMods(NSUInteger mods)
- (BOOL) windowClosingImpl: (BOOL) force
{
jboolean closed = JNI_FALSE;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
-
- [self cursorHide: NO];
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
+ NewtView* newtView = (NewtView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtView class]] ) {
+ return NO;
}
- NewtView* view = (NewtView *) nsview;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [newtView cursorHide: NO enter: -1];
- if( false == [view getDestroyNotifySent] ) {
- jobject javaWindowObject = [view getJavaWindowObject];
+ if( false == [newtView getDestroyNotifySent] ) {
+ jobject javaWindowObject = [newtView getJavaWindowObject];
DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
if (javaWindowObject == NULL) {
DBG_PRINT("windowWillClose: null javaWindowObject\n");
- return;
+ [pool release];
+ return NO;
}
int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
if(NULL==env) {
DBG_PRINT("windowWillClose: null JNIEnv\n");
- return;
+ [pool release];
+ return NO;
}
-
- [view setDestroyNotifySent: true]; // earmark assumption of being closed
+ [newtView setDestroyNotifySent: true]; // earmark assumption of being closed
closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
if(!force && !closed) {
// not closed on java side, not force -> clear flag
- [view setDestroyNotifySent: false];
+ [newtView setDestroyNotifySent: false];
}
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
} else {
DBG_PRINT( "*************** windowWillClose (skip)\n");
@@ -1010,3 +1211,4 @@ static jint mods2JavaMods(NSUInteger mods)
}
@end
+
diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h
index bb782910e..110f1c493 100644
--- a/src/newt/native/ScreenMode.h
+++ b/src/newt/native/ScreenMode.h
@@ -33,12 +33,17 @@
#ifndef _SCREEN_MODE_H
#define _SCREEN_MODE_H
-#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
-#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
-#define NUM_MONITOR_MODE_PROPERTIES 3 /* ScreenSizeMM[width, height], refresh-rate */
-#define NUM_SCREEN_MODE_PROPERTIES 1 /* rotation */
+#define NUM_RESOLUTION_PROPERTIES 2 /* width, height */
+#define NUM_SURFACE_SIZE_PROPERTIES 1 /* bpp */
+#define NUM_SIZEANDRATE_PROPERTIES 2 /* refresh-rate, flags */
+#define NUM_MONITOR_MODE_PROPERTIES 2 /* id, rotation */
-#define NUM_SCREEN_MODE_PROPERTIES_ALL 8 /* count + the above */
+#define NUM_MONITOR_MODE_PROPERTIES_ALL 8 /* count + the above */
+
+#define MIN_MONITOR_DEVICE_PROPERTIES 11 /* count + id, ScreenSizeMM[width, height], rotated Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+ */
+
+#define FLAG_INTERLACE ( 1 << 0 )
+#define FLAG_DOUBLESCAN ( 1 << 1 )
#endif
diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h
index 4755c4fc5..d9ee5fd1f 100644
--- a/src/newt/native/Window.h
+++ b/src/newt/native/Window.h
@@ -38,8 +38,9 @@
#define FLAG_HAS_PARENT ( 1 << 8 )
#define FLAG_IS_UNDECORATED ( 1 << 9 )
#define FLAG_IS_FULLSCREEN ( 1 << 10 )
-#define FLAG_IS_ALWAYSONTOP ( 1 << 11 )
-#define FLAG_IS_VISIBLE ( 1 << 12 )
+#define FLAG_IS_FULLSCREEN_SPAN ( 1 << 11 )
+#define FLAG_IS_ALWAYSONTOP ( 1 << 12 )
+#define FLAG_IS_VISIBLE ( 1 << 13 )
#define TST_FLAG_CHANGE_PARENTING(f) ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) )
#define TST_FLAG_CHANGE_DECORATION(f) ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) )
@@ -47,11 +48,11 @@
#define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) )
#define TST_FLAG_CHANGE_VISIBILITY(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) )
-#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
-#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
-#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
-#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
+#define TST_FLAG_HAS_PARENT(f) ( 0 != ( (f) & FLAG_HAS_PARENT ) )
+#define TST_FLAG_IS_UNDECORATED(f) ( 0 != ( (f) & FLAG_IS_UNDECORATED ) )
+#define TST_FLAG_IS_FULLSCREEN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) )
+#define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) )
+#define TST_FLAG_IS_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) )
+#define TST_FLAG_IS_VISIBLE(f) ( 0 != ( (f) & FLAG_IS_VISIBLE ) )
#endif
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 6d9c04dc3..c20e156c1 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -32,6 +32,16 @@
*
*/
+//
+// Min. required version Windows 7 (For WM_TOUCH)
+//
+#if WINVER < 0x0601
+#error WINVER must be >= 0x0601
+#endif
+#if _WIN32_WINNT < 0x0601
+#error _WIN32_WINNT must be >= 0x0601
+#endif
+
#include <Windows.h>
#include <Windowsx.h>
#include <tchar.h>
@@ -49,13 +59,22 @@
#define strdup(s) _strdup(s)
#endif
+/* GetProcAddress doesn't exist in A/W variants under desktop Windows */
+#ifndef UNDER_CE
+#define GetProcAddressA GetProcAddress
+#endif
+
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif //WM_MOUSEWHEEL
-#ifndef WHEEL_DELTA
-#define WHEEL_DELTA 120
-#endif //WHEEL_DELTA
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif //WM_MOUSEHWHEEL
+
+#ifndef WHEEL_DELTAf
+#define WHEEL_DELTAf (120.0f)
+#endif //WHEEL_DELTAf
#ifndef WHEEL_PAGESCROLL
#define WHEEL_PAGESCROLL (UINT_MAX)
@@ -64,6 +83,30 @@
#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500)
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
#endif
+#ifndef GET_KEYSTATE_WPARAM
+#define GET_KEYSTATE_WPARAM(wParam) ((short)LOWORD(wParam))
+#endif
+
+#ifndef WM_HSCROLL
+#define WM_HSCROLL 0x0114
+#endif
+#ifndef WM_VSCROLL
+#define WM_VSCROLL 0x0115
+#endif
+
+#ifndef WH_MOUSE
+#define WH_MOUSE 7
+#endif
+#ifndef WH_MOUSE_LL
+#define WH_MOUSE_LL 14
+#endif
+
+#ifndef WM_TOUCH
+#define WM_TOUCH 0x0240
+#endif
+#ifndef TOUCH_COORD_TO_PIXEL
+#define TOUCH_COORD_TO_PIXEL(l) (l/100)
+#endif
#ifndef MONITOR_DEFAULTTONULL
#define MONITOR_DEFAULTTONULL 0
@@ -80,10 +123,13 @@
#ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif
+#ifndef DM_INTERLACED
+#define DM_INTERLACED 2
+#endif
-#include "jogamp_newt_driver_windows_WindowsDisplay.h"
-#include "jogamp_newt_driver_windows_WindowsScreen.h"
-#include "jogamp_newt_driver_windows_WindowsWindow.h"
+#include "jogamp_newt_driver_windows_DisplayDriver.h"
+#include "jogamp_newt_driver_windows_ScreenDriver.h"
+#include "jogamp_newt_driver_windows_WindowDriver.h"
#include "Window.h"
#include "MouseEvent.h"
@@ -111,504 +157,442 @@ static jmethodID focusChangedID = NULL;
static jmethodID visibleChangedID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
+static jmethodID sendTouchScreenEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
+typedef WINBOOL (WINAPI *CloseTouchInputHandlePROCADDR)(HANDLE hTouchInput);
+typedef WINBOOL (WINAPI *GetTouchInputInfoPROCADDR)(HANDLE hTouchInput, UINT cInputs, PTOUCHINPUT pInputs, int cbSize);
+typedef WINBOOL (WINAPI *IsTouchWindowPROCADDR)(HWND hWnd,PULONG pulFlags);
+typedef WINBOOL (WINAPI *RegisterTouchWindowPROCADDR)(HWND hWnd,ULONG ulFlags);
+typedef WINBOOL (WINAPI *UnregisterTouchWindowPROCADDR)(HWND hWnd);
+
+static int WinTouch_func_avail = 0;
+static CloseTouchInputHandlePROCADDR WinTouch_CloseTouchInputHandle = NULL;
+static GetTouchInputInfoPROCADDR WinTouch_GetTouchInputInfo = NULL;
+static IsTouchWindowPROCADDR WinTouch_IsTouchWindow = NULL;
+static RegisterTouchWindowPROCADDR WinTouch_RegisterTouchWindow = NULL;
+static UnregisterTouchWindowPROCADDR WinTouch_UnregisterTouchWindow = NULL;
+
static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd);
typedef struct {
JNIEnv* jenv;
jobject jinstance;
+ /* client size width */
+ int width;
+ /* client size height */
+ int height;
+ /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */
+ int setPointerVisible;
+ /** Tristate: -1 RESET, 0 NOP, 1 SET-NEW */
+ int setPointerAction;
+ HCURSOR setPointerHandle;
+ HCURSOR defPointerHandle;
+ /** Bool: 0 NOP, 1 FULLSCREEN */
+ int isFullscreen;
+ /** Bool: 0 TOP, 1 CHILD */
+ int isChildWindow;
+ int pointerCaptured;
+ int pointerInside;
+ int touchDownCount;
+ int touchDownLastUp; // mitigate LBUTTONUP after last TOUCH lift
+ int supportsMTouch;
} WindowUserData;
typedef struct {
- UINT javaKey;
- UINT windowsKey;
+ USHORT javaKey;
+ USHORT windowsKey;
+ USHORT windowsScanCodeUS;
} KeyMapEntry;
// Static table, arranged more or less spatially.
static KeyMapEntry keyMapTable[] = {
// Modifier keys
- {J_VK_CAPS_LOCK, VK_CAPITAL},
- {J_VK_SHIFT, VK_SHIFT},
- {J_VK_CONTROL, VK_CONTROL},
- {J_VK_ALT, VK_MENU},
- {J_VK_NUM_LOCK, VK_NUMLOCK},
+ {J_VK_CAPS_LOCK, VK_CAPITAL, 0},
+ {J_VK_SHIFT, VK_SHIFT, 0},
+ {J_VK_SHIFT, VK_LSHIFT, 0},
+ {J_VK_SHIFT, VK_RSHIFT, 0},
+ {J_VK_CONTROL, VK_CONTROL, 0},
+ {J_VK_CONTROL, VK_LCONTROL, 0},
+ {J_VK_CONTROL, VK_RCONTROL, 0},
+ {J_VK_ALT, VK_MENU, 0},
+ {J_VK_ALT, VK_LMENU, 0},
+ {J_VK_ALT_GRAPH, VK_RMENU, 0},
+ {J_VK_NUM_LOCK, VK_NUMLOCK, 0},
// Miscellaneous Windows keys
- {J_VK_WINDOWS, VK_LWIN},
- {J_VK_WINDOWS, VK_RWIN},
- {J_VK_CONTEXT_MENU, VK_APPS},
+ {J_VK_WINDOWS, VK_LWIN, 0},
+ {J_VK_WINDOWS, VK_RWIN, 0},
+ {J_VK_CONTEXT_MENU, VK_APPS, 0},
// Alphabet
- {J_VK_A, 'A'},
- {J_VK_B, 'B'},
- {J_VK_C, 'C'},
- {J_VK_D, 'D'},
- {J_VK_E, 'E'},
- {J_VK_F, 'F'},
- {J_VK_G, 'G'},
- {J_VK_H, 'H'},
- {J_VK_I, 'I'},
- {J_VK_J, 'J'},
- {J_VK_K, 'K'},
- {J_VK_L, 'L'},
- {J_VK_M, 'M'},
- {J_VK_N, 'N'},
- {J_VK_O, 'O'},
- {J_VK_P, 'P'},
- {J_VK_Q, 'Q'},
- {J_VK_R, 'R'},
- {J_VK_S, 'S'},
- {J_VK_T, 'T'},
- {J_VK_U, 'U'},
- {J_VK_V, 'V'},
- {J_VK_W, 'W'},
- {J_VK_X, 'X'},
- {J_VK_Y, 'Y'},
- {J_VK_Z, 'Z'},
- {J_VK_0, '0'},
- {J_VK_1, '1'},
- {J_VK_2, '2'},
- {J_VK_3, '3'},
- {J_VK_4, '4'},
- {J_VK_5, '5'},
- {J_VK_6, '6'},
- {J_VK_7, '7'},
- {J_VK_8, '8'},
- {J_VK_9, '9'},
- {J_VK_ENTER, VK_RETURN},
- {J_VK_SPACE, VK_SPACE},
- {J_VK_BACK_SPACE, VK_BACK},
- {J_VK_TAB, VK_TAB},
- {J_VK_ESCAPE, VK_ESCAPE},
- {J_VK_INSERT, VK_INSERT},
- {J_VK_DELETE, VK_DELETE},
- {J_VK_HOME, VK_HOME},
- {J_VK_END, VK_END},
- {J_VK_PAGE_UP, VK_PRIOR},
- {J_VK_PAGE_DOWN, VK_NEXT},
- {J_VK_CLEAR, VK_CLEAR}, // NumPad 5
+ {J_VK_A, 'A', 0},
+ {J_VK_B, 'B', 0},
+ {J_VK_C, 'C', 0},
+ {J_VK_D, 'D', 0},
+ {J_VK_E, 'E', 0},
+ {J_VK_F, 'F', 0},
+ {J_VK_G, 'G', 0},
+ {J_VK_H, 'H', 0},
+ {J_VK_I, 'I', 0},
+ {J_VK_J, 'J', 0},
+ {J_VK_K, 'K', 0},
+ {J_VK_L, 'L', 0},
+ {J_VK_M, 'M', 0},
+ {J_VK_N, 'N', 0},
+ {J_VK_O, 'O', 0},
+ {J_VK_P, 'P', 0},
+ {J_VK_Q, 'Q', 0},
+ {J_VK_R, 'R', 0},
+ {J_VK_S, 'S', 0},
+ {J_VK_T, 'T', 0},
+ {J_VK_U, 'U', 0},
+ {J_VK_V, 'V', 0},
+ {J_VK_W, 'W', 0},
+ {J_VK_X, 'X', 0},
+ {J_VK_Y, 'Y', 0},
+ {J_VK_Z, 'Z', 0},
+ {J_VK_0, '0', 0},
+ {J_VK_1, '1', 0},
+ {J_VK_2, '2', 0},
+ {J_VK_3, '3', 0},
+ {J_VK_4, '4', 0},
+ {J_VK_5, '5', 0},
+ {J_VK_6, '6', 0},
+ {J_VK_7, '7', 0},
+ {J_VK_8, '8', 0},
+ {J_VK_9, '9', 0},
+ {J_VK_ENTER, VK_RETURN, 0},
+ {J_VK_SPACE, VK_SPACE, 0},
+ {J_VK_BACK_SPACE, VK_BACK, 0},
+ {J_VK_TAB, VK_TAB, 0},
+ {J_VK_ESCAPE, VK_ESCAPE, 0},
+ {J_VK_INSERT, VK_INSERT, 0},
+ {J_VK_DELETE, VK_DELETE, 0},
+ {J_VK_HOME, VK_HOME, 0},
+ // {J_VK_BEGIN, VK_BEGIN, 0}, // not mapped
+ {J_VK_END, VK_END, 0},
+ {J_VK_PAGE_UP, VK_PRIOR, 0},
+ {J_VK_PAGE_DOWN, VK_NEXT, 0},
+ {J_VK_CLEAR, VK_CLEAR, 0}, // NumPad 5
// NumPad with NumLock off & extended arrows block (triangular)
- {J_VK_LEFT, VK_LEFT},
- {J_VK_RIGHT, VK_RIGHT},
- {J_VK_UP, VK_UP},
- {J_VK_DOWN, VK_DOWN},
+ {J_VK_LEFT, VK_LEFT, 0},
+ {J_VK_RIGHT, VK_RIGHT, 0},
+ {J_VK_UP, VK_UP, 0},
+ {J_VK_DOWN, VK_DOWN, 0},
// NumPad with NumLock on: numbers
- {J_VK_NUMPAD0, VK_NUMPAD0},
- {J_VK_NUMPAD1, VK_NUMPAD1},
- {J_VK_NUMPAD2, VK_NUMPAD2},
- {J_VK_NUMPAD3, VK_NUMPAD3},
- {J_VK_NUMPAD4, VK_NUMPAD4},
- {J_VK_NUMPAD5, VK_NUMPAD5},
- {J_VK_NUMPAD6, VK_NUMPAD6},
- {J_VK_NUMPAD7, VK_NUMPAD7},
- {J_VK_NUMPAD8, VK_NUMPAD8},
- {J_VK_NUMPAD9, VK_NUMPAD9},
+ {J_VK_NUMPAD0, VK_NUMPAD0, 0},
+ {J_VK_NUMPAD1, VK_NUMPAD1, 0},
+ {J_VK_NUMPAD2, VK_NUMPAD2, 0},
+ {J_VK_NUMPAD3, VK_NUMPAD3, 0},
+ {J_VK_NUMPAD4, VK_NUMPAD4, 0},
+ {J_VK_NUMPAD5, VK_NUMPAD5, 0},
+ {J_VK_NUMPAD6, VK_NUMPAD6, 0},
+ {J_VK_NUMPAD7, VK_NUMPAD7, 0},
+ {J_VK_NUMPAD8, VK_NUMPAD8, 0},
+ {J_VK_NUMPAD9, VK_NUMPAD9, 0},
// NumPad with NumLock on
- {J_VK_MULTIPLY, VK_MULTIPLY},
- {J_VK_ADD, VK_ADD},
- {J_VK_SEPARATOR, VK_SEPARATOR},
- {J_VK_SUBTRACT, VK_SUBTRACT},
- {J_VK_DECIMAL, VK_DECIMAL},
- {J_VK_DIVIDE, VK_DIVIDE},
+ {J_VK_MULTIPLY, VK_MULTIPLY, 0},
+ {J_VK_ADD, VK_ADD, 0},
+ {J_VK_SEPARATOR, VK_SEPARATOR, 0},
+ {J_VK_SUBTRACT, VK_SUBTRACT, 0},
+ {J_VK_DECIMAL, VK_DECIMAL, 0},
+ {J_VK_DIVIDE, VK_DIVIDE, 0},
// Functional keys
- {J_VK_F1, VK_F1},
- {J_VK_F2, VK_F2},
- {J_VK_F3, VK_F3},
- {J_VK_F4, VK_F4},
- {J_VK_F5, VK_F5},
- {J_VK_F6, VK_F6},
- {J_VK_F7, VK_F7},
- {J_VK_F8, VK_F8},
- {J_VK_F9, VK_F9},
- {J_VK_F10, VK_F10},
- {J_VK_F11, VK_F11},
- {J_VK_F12, VK_F12},
- {J_VK_F13, VK_F13},
- {J_VK_F14, VK_F14},
- {J_VK_F15, VK_F15},
- {J_VK_F16, VK_F16},
- {J_VK_F17, VK_F17},
- {J_VK_F18, VK_F18},
- {J_VK_F19, VK_F19},
- {J_VK_F20, VK_F20},
- {J_VK_F21, VK_F21},
- {J_VK_F22, VK_F22},
- {J_VK_F23, VK_F23},
- {J_VK_F24, VK_F24},
-
- {J_VK_PRINTSCREEN, VK_SNAPSHOT},
- {J_VK_SCROLL_LOCK, VK_SCROLL},
- {J_VK_PAUSE, VK_PAUSE},
- {J_VK_CANCEL, VK_CANCEL},
- {J_VK_HELP, VK_HELP},
+ {J_VK_F1, VK_F1, 0},
+ {J_VK_F2, VK_F2, 0},
+ {J_VK_F3, VK_F3, 0},
+ {J_VK_F4, VK_F4, 0},
+ {J_VK_F5, VK_F5, 0},
+ {J_VK_F6, VK_F6, 0},
+ {J_VK_F7, VK_F7, 0},
+ {J_VK_F8, VK_F8, 0},
+ {J_VK_F9, VK_F9, 0},
+ {J_VK_F10, VK_F10, 0},
+ {J_VK_F11, VK_F11, 0},
+ {J_VK_F12, VK_F12, 0},
+ {J_VK_F13, VK_F13, 0},
+ {J_VK_F14, VK_F14, 0},
+ {J_VK_F15, VK_F15, 0},
+ {J_VK_F16, VK_F16, 0},
+ {J_VK_F17, VK_F17, 0},
+ {J_VK_F18, VK_F18, 0},
+ {J_VK_F19, VK_F19, 0},
+ {J_VK_F20, VK_F20, 0},
+ {J_VK_F21, VK_F21, 0},
+ {J_VK_F22, VK_F22, 0},
+ {J_VK_F23, VK_F23, 0},
+ {J_VK_F24, VK_F24, 0},
+
+ {J_VK_PRINTSCREEN, VK_SNAPSHOT, 0},
+ {J_VK_SCROLL_LOCK, VK_SCROLL, 0},
+ {J_VK_PAUSE, VK_PAUSE, 0},
+ {J_VK_CANCEL, VK_CANCEL, 0},
+ {J_VK_HELP, VK_HELP, 0},
+
+ // Since we unify mappings via US kbd layout .. this is valid:
+ {J_VK_SEMICOLON, VK_OEM_1, 0}, // US only ';:'
+ {J_VK_EQUALS, VK_OEM_PLUS, 0}, // '=+'
+ {J_VK_COMMA, VK_OEM_COMMA, 0}, // ',<'
+ {J_VK_MINUS, VK_OEM_MINUS, 0}, // '-_'
+ {J_VK_PERIOD, VK_OEM_PERIOD, 0}, // '.>'
+ {J_VK_SLASH, VK_OEM_2, 0}, // US only '/?'
+ {J_VK_BACK_QUOTE, VK_OEM_3, 0}, // US only '`~'
+ {J_VK_OPEN_BRACKET, VK_OEM_4, 0}, // US only '[}'
+ {J_VK_BACK_SLASH, VK_OEM_5, 0}, // US only '\|'
+ {J_VK_CLOSE_BRACKET, VK_OEM_6, 0}, // US only ']}'
+ {J_VK_QUOTE, VK_OEM_7, 0}, // US only ''"'
+ // {J_VK_????, VK_OEM_8, 0}, // varies ..
+ // {J_VK_????, VK_OEM_102, 0}, // angle-bracket or backslash key on RT 102-key kbd
// Japanese
/*
- {J_VK_CONVERT, VK_CONVERT},
- {J_VK_NONCONVERT, VK_NONCONVERT},
- {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI},
- {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC},
- {J_VK_KATAKANA, VK_DBE_KATAKANA},
- {J_VK_HIRAGANA, VK_DBE_HIRAGANA},
- {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR},
- {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR},
- {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN},
+ {J_VK_CONVERT, VK_CONVERT, 0},
+ {J_VK_NONCONVERT, VK_NONCONVERT, 0},
+ {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI, 0},
+ {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC, 0},
+ {J_VK_KATAKANA, VK_DBE_KATAKANA, 0},
+ {J_VK_HIRAGANA, VK_DBE_HIRAGANA, 0},
+ {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR, 0},
+ {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR, 0},
+ {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN, 0},
*/
- {J_VK_UNDEFINED, 0}
-};
-
-/*
-Dynamic mapping table for OEM VK codes. This table is refilled
-by BuildDynamicKeyMapTable when keyboard layout is switched.
-(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values).
-*/
-typedef struct {
- // OEM VK codes known in advance
- UINT windowsKey;
- // depends on input langauge (kbd layout)
- UINT javaKey;
-} DynamicKeyMapEntry;
-
-static DynamicKeyMapEntry dynamicKeyMapTable[] = {
- {0x00BA, J_VK_UNDEFINED}, // VK_OEM_1
- {0x00BB, J_VK_UNDEFINED}, // VK_OEM_PLUS
- {0x00BC, J_VK_UNDEFINED}, // VK_OEM_COMMA
- {0x00BD, J_VK_UNDEFINED}, // VK_OEM_MINUS
- {0x00BE, J_VK_UNDEFINED}, // VK_OEM_PERIOD
- {0x00BF, J_VK_UNDEFINED}, // VK_OEM_2
- {0x00C0, J_VK_UNDEFINED}, // VK_OEM_3
- {0x00DB, J_VK_UNDEFINED}, // VK_OEM_4
- {0x00DC, J_VK_UNDEFINED}, // VK_OEM_5
- {0x00DD, J_VK_UNDEFINED}, // VK_OEM_6
- {0x00DE, J_VK_UNDEFINED}, // VK_OEM_7
- {0x00DF, J_VK_UNDEFINED}, // VK_OEM_8
- {0x00E2, J_VK_UNDEFINED}, // VK_OEM_102
- {0, 0}
+ {J_VK_UNDEFINED, 0, 0}
};
-// Auxiliary tables used to fill the above dynamic table. We first
-// find the character for the OEM VK code using ::MapVirtualKey and
-// then go through these auxiliary tables to map it to Java VK code.
+#ifndef KLF_ACTIVATE
+ #define KLF_ACTIVATE 0x00000001
+#endif
+#ifndef MAPVK_VK_TO_VSC
+ #define MAPVK_VK_TO_VSC 0
+#endif
+#ifndef MAPVK_VSC_TO_VK
+ #define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+ #define MAPVK_VK_TO_CHAR 2
+#endif
+#ifndef MAPVK_VSC_TO_VK_EX
+ #define MAPVK_VSC_TO_VK_EX 3
+#endif
+#ifndef MAPVK_VK_TO_VSC_EX
+ #define MAPVK_VK_TO_VSC_EX 4
+#endif
-typedef struct {
- WCHAR c;
- UINT javaKey;
-} CharToVKEntry;
-
-static const CharToVKEntry charToVKTable[] = {
- {L'!', J_VK_EXCLAMATION_MARK},
- {L'"', J_VK_QUOTEDBL},
- {L'#', J_VK_NUMBER_SIGN},
- {L'$', J_VK_DOLLAR},
- {L'&', J_VK_AMPERSAND},
- {L'\'', J_VK_QUOTE},
- {L'(', J_VK_LEFT_PARENTHESIS},
- {L')', J_VK_RIGHT_PARENTHESIS},
- {L'*', J_VK_ASTERISK},
- {L'+', J_VK_PLUS},
- {L',', J_VK_COMMA},
- {L'-', J_VK_MINUS},
- {L'.', J_VK_PERIOD},
- {L'/', J_VK_SLASH},
- {L':', J_VK_COLON},
- {L';', J_VK_SEMICOLON},
- {L'<', J_VK_LESS},
- {L'=', J_VK_EQUALS},
- {L'>', J_VK_GREATER},
- {L'@', J_VK_AT},
- {L'[', J_VK_OPEN_BRACKET},
- {L'\\', J_VK_BACK_SLASH},
- {L']', J_VK_CLOSE_BRACKET},
- {L'^', J_VK_CIRCUMFLEX},
- {L'_', J_VK_UNDERSCORE},
- {L'`', J_VK_BACK_QUOTE},
- {L'{', J_VK_BRACELEFT},
- {L'}', J_VK_BRACERIGHT},
- {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK},
- {0x20A0, J_VK_EURO_SIGN}, // ????
- {0,0}
-};
+#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
-// For dead accents some layouts return ASCII punctuation, while some
-// return spacing accent chars, so both should be listed. NB: MS docs
-// say that conversion routings return spacing accent character, not
-// combining.
-static const CharToVKEntry charToDeadVKTable[] = {
- {L'`', J_VK_DEAD_GRAVE},
- {L'\'', J_VK_DEAD_ACUTE},
- {0x00B4, J_VK_DEAD_ACUTE},
- {L'^', J_VK_DEAD_CIRCUMFLEX},
- {L'~', J_VK_DEAD_TILDE},
- {0x02DC, J_VK_DEAD_TILDE},
- {0x00AF, J_VK_DEAD_MACRON},
- {0x02D8, J_VK_DEAD_BREVE},
- {0x02D9, J_VK_DEAD_ABOVEDOT},
- {L'"', J_VK_DEAD_DIAERESIS},
- {0x00A8, J_VK_DEAD_DIAERESIS},
- {0x02DA, J_VK_DEAD_ABOVERING},
- {0x02DD, J_VK_DEAD_DOUBLEACUTE},
- {0x02C7, J_VK_DEAD_CARON}, // aka hacek
- {L',', J_VK_DEAD_CEDILLA},
- {0x00B8, J_VK_DEAD_CEDILLA},
- {0x02DB, J_VK_DEAD_OGONEK},
- {0x037A, J_VK_DEAD_IOTA}, // ASCII ???
- {0x309B, J_VK_DEAD_VOICED_SOUND},
- {0x309C, J_VK_DEAD_SEMIVOICED_SOUND},
- {0,0}
-};
+static HKL kbdLayoutUS = 0;
+static const LPCSTR US_LAYOUT_NAME = "00000409";
-// ANSI CP identifiers are no longer than this
-#define MAX_ACP_STR_LEN 7
+static BYTE kbdState[256];
+static USHORT spaceScanCode;
-static void BuildDynamicKeyMapTable()
-{
+static void InitKeyMapTableScanCode(JNIEnv *env) {
HKL hkl = GetKeyboardLayout(0);
- // Will need this to reset layout after dead keys.
- UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl);
- DynamicKeyMapEntry *dynamic;
-
- LANGID idLang = LOWORD(GetKeyboardLayout(0));
- UINT codePage;
- TCHAR strCodePage[MAX_ACP_STR_LEN];
- // use the LANGID to create a LCID
- LCID idLocale = MAKELCID(idLang, SORT_DEFAULT);
- // get the ANSI code page associated with this locale
- if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE,
- strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 )
- {
- codePage = _ttoi(strCodePage);
- } else {
- codePage = GetACP();
+ int i;
+
+ kbdLayoutUS = LoadKeyboardLayout( US_LAYOUT_NAME, 0 /* ? KLF_ACTIVATE ? */ );
+ if( 0 == kbdLayoutUS ) {
+ int lastError = (int) GetLastError();
+ kbdLayoutUS = hkl; // use prev. layout .. well
+ STD_PRINT("Warning: NEWT Windows: LoadKeyboardLayout(US, ..) failed: winErr 0x%X %d\n", lastError, lastError);
}
+ ActivateKeyboardLayout(hkl, 0);
- // Entries in dynamic table that maps between Java VK and Windows
- // VK are built in three steps:
- // 1. Map windows VK to ANSI character (cannot map to unicode
- // directly, since ::ToUnicode is not implemented on win9x)
- // 2. Convert ANSI char to Unicode char
- // 3. Map Unicode char to Java VK via two auxilary tables.
+ spaceScanCode = MapVirtualKeyEx(VK_SPACE, MAPVK_VK_TO_VSC, hkl);
- for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic)
- {
- char cbuf[2] = { '\0', '\0'};
- WCHAR ucbuf[2] = { L'\0', L'\0' };
- int nchars;
- UINT scancode;
- const CharToVKEntry *charMap;
- int nconverted;
- WCHAR uc;
- BYTE kbdState[256];
-
- // Defaults to J_VK_UNDEFINED
- dynamic->javaKey = J_VK_UNDEFINED;
-
- GetKeyboardState(kbdState);
-
- kbdState[dynamic->windowsKey] |= 0x80; // Press the key.
-
- // Unpress modifiers, since they are most likely pressed as
- // part of the keyboard switching shortcut.
- kbdState[VK_CONTROL] &= ~0x80;
- kbdState[VK_SHIFT] &= ~0x80;
- kbdState[VK_MENU] &= ~0x80;
-
- scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl);
- nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState,
- (WORD*)cbuf, 0, hkl);
-
- // Auxiliary table used to map Unicode character to Java VK.
- // Will assign a different table for dead keys (below).
- charMap = charToVKTable;
-
- if (nchars < 0) { // Dead key
- char junkbuf[2] = { '\0', '\0'};
- // Use a different table for dead chars since different layouts
- // return different characters for the same dead key.
- charMap = charToDeadVKTable;
-
- // We also need to reset layout so that next translation
- // is unaffected by the dead status. We do this by
- // translating <SPACE> key.
- kbdState[dynamic->windowsKey] &= ~0x80;
- kbdState[VK_SPACE] |= 0x80;
-
- ToAsciiEx(VK_SPACE, spaceScanCode, kbdState,
- (WORD*)junkbuf, 0, hkl);
+ // Setup keyMapTable's windowsScanCodeUS
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ USHORT scancode = (USHORT) MapVirtualKeyEx(keyMapTable[i].windowsKey, MAPVK_VK_TO_VSC_EX, kbdLayoutUS);
+ #ifdef DEBUG_KEYS
+ if( 0 == scancode ) {
+ int lastError = (int) GetLastError();
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: No ScanCode for windows vkey 0x%X (item %d), winErr 0x%X %d\n",
+ keyMapTable[i].windowsKey, i, lastError, lastError);
}
+ STD_PRINT("*** WindowsWindow: InitKeyMapTableScanCode: %3.3d windows vkey 0x%X -> scancode 0x%X\n",
+ i, keyMapTable[i].windowsKey, scancode);
+ #endif
+ keyMapTable[i].windowsScanCodeUS = scancode;
+ }
+}
- nconverted = MultiByteToWideChar(codePage, 0,
- cbuf, 1, ucbuf, 2);
+static void ParseWmVKeyAndScanCode(USHORT winVKey, BYTE winScanCode, BYTE flags, USHORT *outJavaVKeyUS, USHORT *outJavaVKeyXX, USHORT *outUTF16Char) {
+ wchar_t uniChars[2] = { L'\0', L'\0' }; // uint16_t
+ USHORT winVKeyUS = 0;
+ int nUniChars, i, j;
+ USHORT javaVKeyUS = J_VK_UNDEFINED;
+ USHORT javaVKeyXX = J_VK_UNDEFINED;
- uc = ucbuf[0];
- {
- const CharToVKEntry *map;
- for (map = charMap; map->c != 0; ++map) {
- if (uc == map->c) {
- dynamic->javaKey = map->javaKey;
- break;
- }
+ HKL hkl = GetKeyboardLayout(0);
+
+ //
+ // winVKey, winScanCode -> UTF16 w/ current KeyboardLayout
+ //
+ GetKeyboardState(kbdState);
+ kbdState[winVKey] |= 0x80;
+ nUniChars = ToUnicodeEx(winVKey, winScanCode, kbdState, uniChars, 2, 0, hkl);
+ kbdState[winVKey] &= ~0x80;
+
+ *outUTF16Char = (USHORT)(uniChars[0]); // Note: Even dead key are written in uniChar's ..
+
+ if ( 0 > nUniChars ) { // Dead key
+ char junkbuf[2] = { '\0', '\0'};
+
+ // We need to reset layout so that next translation
+ // is unaffected by the dead status. We do this by
+ // translating <SPACE> key.
+ kbdState[VK_SPACE] |= 0x80;
+ ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, (WORD*)junkbuf, 0, hkl);
+ kbdState[VK_SPACE] &= ~0x80;
+ }
+
+ //
+ // winVKey -> javaVKeyXX
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsKey == winVKey ) {
+ javaVKeyXX = keyMapTable[i].javaKey;
+ break;
+ }
+ }
+ if( IS_WITHIN( winVKey, VK_NUMPAD0, VK_DIVIDE ) ) {
+ // Use modded keySym for keypad for US and NN
+ winVKeyUS = winVKey;
+ javaVKeyUS = javaVKeyXX;
+ } else {
+ // Assume extended scan code 0xE0 if extended flags is set (no 0xE1 from WM_KEYUP/WM_KEYDOWN)
+ USHORT winScanCodeExt = winScanCode;
+ if( 0 != ( 0x01 & flags ) ) {
+ winScanCodeExt |= 0xE000;
+ }
+
+ //
+ // winVKey, winScanCodeExt -> javaVKeyUS w/ US KeyboardLayout
+ //
+ for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
+ if ( keyMapTable[i].windowsScanCodeUS == winScanCodeExt ) {
+ winVKeyUS = keyMapTable[i].windowsKey;
+ javaVKeyUS = keyMapTable[i].javaKey;
+ break;
}
}
+ if( J_VK_UNDEFINED == javaVKeyUS ) {
+ javaVKeyUS = javaVKeyXX;
+ }
+ }
+
+ *outJavaVKeyUS = javaVKeyUS;
+ *outJavaVKeyXX = javaVKeyXX;
- } // for each VK_OEM_*
+#ifdef DEBUG_KEYS
+ STD_PRINT("*** WindowsWindow: ParseWmVKeyAndScanCode winVKey 0x%X, winScanCode 0x%X, flags 0x%X -> UTF(0x%X, %c, res %d, sizeof %d), vKeys( US(win 0x%X, java 0x%X), XX(win 0x%X, java 0x%X))\n",
+ (int)winVKey, (int)winScanCode, (int)flags,
+ *outUTF16Char, *outUTF16Char, nUniChars, sizeof(uniChars[0]),
+ winVKeyUS, javaVKeyUS, winVKey, javaVKeyXX);
+#endif
}
-static jint GetModifiers() {
+static jint GetModifiers(USHORT jkey) {
jint modifiers = 0;
// have to do &0xFFFF to avoid runtime assert caused by compiling with
// /RTCcsu
- if (HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_CONTROL) & 0xFFFF)) != 0 || J_VK_CONTROL == jkey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if (HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_SHIFT) & 0xFFFF)) != 0 || J_VK_SHIFT == jkey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if (HIBYTE((GetKeyState(VK_MENU) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_LMENU) & 0xFFFF)) != 0 || J_VK_ALT == jkey ) {
modifiers |= EVENT_ALT_MASK;
}
- if (HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RMENU) & 0xFFFF)) != 0 || (USHORT)J_VK_ALT_GRAPH == jkey ) {
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ }
+ if ( HIBYTE((GetKeyState(VK_LBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if (HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_MBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if (HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0) {
+ if ( HIBYTE((GetKeyState(VK_RBUTTON) & 0xFFFF)) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
return modifiers;
}
-static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt,
- UINT flags, BOOL system)
-{
+/**
+static BOOL IsAltKeyDown(BYTE flags, BOOL system) {
// The Alt modifier is reported in the 29th bit of the lParam,
- // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)).
- BOOL alt_is_down = (flags & (1<<13)) != 0;
- if (system && alt_is_down) {
- if (character == VK_SPACE) {
- return 1;
- }
- }
-
- if (character == VK_RETURN) {
- character = J_VK_ENTER;
- }
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) character);
- return 1;
-}
-
-UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers)
-{
- int i, j;
- // for the general case, use a bi-directional table
- for (i = 0; keyMapTable[i].windowsKey != 0; i++) {
- if (keyMapTable[i].windowsKey == windowsKey) {
- return keyMapTable[i].javaKey;
- }
- }
- for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
- if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
- if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) {
- return dynamicKeyMapTable[j].javaKey;
- } else {
- break;
- }
- }
- }
-
- return J_VK_UNDEFINED;
-}
+ // i.e., it is the 5th bit of `flags' (which is HIBYTE(HIWORD(lParam))).
+ return system && ( flags & (1<<5) ) != 0;
+} */
-static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_PRESSED,
- modifiers,
- (jint) jkey,
- (jchar) character);
-
- /* windows does not create a WM_CHAR for the Del key
- for some reason, so we need to create the KEY_TYPED event on the
- WM_KEYDOWN.
- */
- if (jkey == J_VK_DELETE) {
- (*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_TYPED,
- GetModifiers(),
- (jint) -1,
- (jchar) '\177');
- }
+ (jshort) EVENT_KEY_PRESSED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
-static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt,
- UINT flags, BOOL system)
-{
- UINT modifiers = 0, jkey = 0, character = -1;
+static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE scanCode, BYTE flags, BOOL system) {
+ UINT modifiers = 0;
+ USHORT javaVKeyUS=0, javaVKeyXX=0, utf16Char=0;
if (wkey == VK_PROCESSKEY) {
return 1;
}
- modifiers = GetModifiers();
- jkey = WindowsKeyToJavaKey(wkey, modifiers);
-/*
- character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
-*/
+ ParseWmVKeyAndScanCode(wkey, scanCode, flags, &javaVKeyUS, &javaVKeyXX, &utf16Char);
+
+ modifiers = GetModifiers( javaVKeyUS );
(*env)->CallVoidMethod(env, window, sendKeyEventID,
- (jint) EVENT_KEY_RELEASED,
- modifiers,
- (jint) jkey,
- (jchar) character);
+ (jshort) EVENT_KEY_RELEASED,
+ (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char);
return 0;
}
static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jboolean force) {
HWND pHwnd, current;
+ BOOL isEnabled = IsWindowEnabled(hwnd);
pHwnd = GetParent(hwnd);
current = GetFocus();
- DBG_PRINT("*** WindowsWindow: requestFocus.S parent %p, window %p, isCurrent %d\n",
- (void*) pHwnd, (void*)hwnd, current==hwnd);
+ DBG_PRINT("*** WindowsWindow: requestFocus.S force %d, parent %p, window %p, isEnabled %d, isCurrent %d\n",
+ (int)force, (void*)pHwnd, (void*)hwnd, isEnabled, current==hwnd);
- if( JNI_TRUE==force || current!=hwnd) {
+ if( JNI_TRUE==force || current!=hwnd || !isEnabled ) {
UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if(!isEnabled) {
+ EnableWindow(hwnd, TRUE);
+ }
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags);
SetForegroundWindow(hwnd); // Slightly Higher Priority
- SetFocus(hwnd);// Sets Keyboard Focus To Window
+ SetFocus(hwnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
if(NULL!=pHwnd) {
SetActiveWindow(hwnd);
}
- DBG_PRINT("*** WindowsWindow: requestFocus.X1\n");
+ current = GetFocus();
+ DBG_PRINT("*** WindowsWindow: requestFocus.X1 isCurrent %d\n", current==hwnd);
}
DBG_PRINT("*** WindowsWindow: requestFocus.XX\n");
}
@@ -620,7 +604,33 @@ static void NewtWindows_trackPointerLeave(HWND hwnd) {
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
tme.dwHoverTime = 0; // we don't use TME_HOVER
- TrackMouseEvent(&tme);
+ BOOL ok = TrackMouseEvent(&tme);
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: %d\n", ok);
+ #ifdef VERBOSE_ON
+ if(!ok) {
+ int lastError = (int) GetLastError();
+ DBG_PRINT( "*** WindowsWindow: trackPointerLeave: lastError 0x%X %d\n", lastError, lastError);
+ }
+ #endif
+ (void)ok;
+}
+
+static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
+{
+ int flags = 0;
+ DEVMODE dm;
+
+ // initialize the DEVMODE structure
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
+ {
+ return JNI_FALSE;
+ }
+ flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
+
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
}
#if 0
@@ -711,7 +721,7 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
{
LONG style = GetWindowLong(hwnd, GWL_STYLE);
- BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP|WS_SYSMENU)) != 0;
+ BOOL bIsUndecorated = (style & (WS_CHILD|WS_POPUP)) != 0;
if (!bIsUndecorated) {
/* Get outer frame sizes. */
if (style & WS_THICKFRAME) {
@@ -745,11 +755,11 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd)
#endif
-static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
+static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type)
{
RECT rc;
- int w, h;
BOOL isVisible = IsWindowVisible(wnd);
+ jobject window = wud->jinstance;
if (type == SIZE_MINIMIZED) {
// TODO: deal with minimized window sizing
@@ -762,29 +772,147 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type)
GetClientRect(wnd, &rc);
// we report back the dimensions of the client area
- w = (int) ( rc.right - rc.left );
- h = (int) ( rc.bottom - rc.top );
+ wud->width = (int) ( rc.right - rc.left );
+ wud->height = (int) ( rc.bottom - rc.top );
- DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible);
+ DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, wud->width, wud->height, isVisible);
- (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE);
}
-static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
- WPARAM wParam, LPARAM lParam)
+#ifdef TEST_MOUSE_HOOKS
+
+static HHOOK hookLLMP;
+static HHOOK hookMP;
+
+static LRESULT CALLBACK HookLowLevelMouseProc (int code, WPARAM wParam, LPARAM lParam)
{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MSLLHOOKSTRUCT *p = (MSLLHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** LLMP: Code: 0x%X: %s - %d/%d\n", code, msg, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** LLMP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookLLMP, code, wParam, lParam);
+}
+
+static LRESULT CALLBACK HookMouseProc (int code, WPARAM wParam, LPARAM lParam)
+{
+ // if (code == HC_ACTION)
+ {
+ const char *msg;
+ char msg_buff[128];
+ switch (wParam)
+ {
+ case WM_LBUTTONDOWN: msg = "WM_LBUTTONDOWN"; break;
+ case WM_LBUTTONUP: msg = "WM_LBUTTONUP"; break;
+ case WM_MOUSEMOVE: msg = "WM_MOUSEMOVE"; break;
+ case WM_MOUSEWHEEL: msg = "WM_MOUSEWHEEL"; break;
+ case WM_MOUSEHWHEEL: msg = "WM_MOUSEHWHEEL"; break;
+ case WM_RBUTTONDOWN: msg = "WM_RBUTTONDOWN"; break;
+ case WM_RBUTTONUP: msg = "WM_RBUTTONUP"; break;
+ default:
+ sprintf(msg_buff, "Unknown msg: %u", wParam);
+ msg = msg_buff;
+ break;
+ }//switch
+
+ const MOUSEHOOKSTRUCT *p = (MOUSEHOOKSTRUCT*)lParam;
+ DBG_PRINT("**** MP: Code: 0x%X: %s - hwnd %p, %d/%d\n", code, msg, p->hwnd, (int)p->pt.x, (int)p->pt.y);
+ //} else {
+ // DBG_PRINT("**** MP: CODE: 0x%X\n", code);
+ }
+ return CallNextHookEx(hookMP, code, wParam, lParam);
+}
+
+#endif
+
+static BOOL SafeShowCursor(BOOL show) {
+ int count, countPre;
+ BOOL b;
+
+ if( show ) {
+ count = ShowCursor(TRUE);
+ if(count < 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(TRUE);
+ } while( count > countPre && count < 0 );
+ }
+ b = count>=0 ? TRUE : FALSE;
+ } else {
+ count = ShowCursor(FALSE);
+ if(count >= 0) {
+ do {
+ countPre = count;
+ count = ShowCursor(FALSE);
+ } while( count < countPre && count >= 0 );
+ }
+ b = count<0 ? TRUE : FALSE;
+ }
+ return b;
+}
+
+static void sendTouchScreenEvent(JNIEnv *env, jobject window,
+ short eventType, int modifiers, int actionIdx,
+ int count, jint* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) {
+ jintArray jNames = (*env)->NewIntArray(env, count);
+ if (jNames == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jNames, 0, count, pointerNames);
+
+ jintArray jX = (*env)->NewIntArray(env, count);
+ if (jX == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jX, 0, count, x);
+
+ jintArray jY = (*env)->NewIntArray(env, count);
+ if (jY == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, jY, 0, count, y);
+
+ jfloatArray jPressure = (*env)->NewFloatArray(env, count);
+ if (jPressure == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", count);
+ }
+ (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure);
+
+ (*env)->CallVoidMethod(env, window, sendTouchScreenEventID,
+ (jshort)eventType, (jint)modifiers, (jint)actionIdx,
+ jNames, jX, jY, jPressure, (jfloat)maxPressure);
+}
+
+
+static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
int useDefWindowProc = 0;
JNIEnv *env = NULL;
jobject window = NULL;
BOOL isKeyDown = FALSE;
WindowUserData * wud;
-
-#ifdef DEBUG_KEYS
- if ( WM_KEYDOWN == message ) {
- STD_PRINT("*** WindowsWindow: wndProc window %p, 0x%X %d/%d\n", wnd, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
- }
-#endif
+ WORD repCnt;
+ BYTE scanCode, flags;
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA);
@@ -797,225 +925,589 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
env = wud->jenv;
window = wud->jinstance;
- // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, 0x%X %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+ // DBG_PRINT("*** WindowsWindow: thread 0x%X - window %p -> %p, msg 0x%X, %d/%d\n", (int)GetCurrentThreadId(), wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
if (NULL==window || NULL==env) {
return DefWindowProc(wnd, message, wParam, lParam);
}
switch (message) {
+ //
+ // The signal pipeline for destruction is:
+ // Java::DestroyWindow(wnd) _or_ window-close-button ->
+ // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
+ case WM_CLOSE:
+ (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
+ break;
- //
- // The signal pipeline for destruction is:
- // Java::DestroyWindow(wnd) _or_ window-close-button ->
- // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY
- case WM_CLOSE:
- (*env)->CallBooleanMethod(env, window, windowDestroyNotifyID, JNI_FALSE);
- break;
-
- case WM_DESTROY:
- {
-#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
- SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
-#else
- SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
-#endif
- free(wud); wud=NULL;
- (*env)->DeleteGlobalRef(env, window);
- }
- break;
+ case WM_DESTROY:
+ {
+ #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ SetWindowLong(wnd, GWL_USERDATA, (intptr_t) NULL);
+ #else
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (intptr_t) NULL);
+ #endif
+ free(wud); wud=NULL;
+ (*env)->DeleteGlobalRef(env, window);
+ }
+ break;
- case WM_SYSCHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_ACTIVATE: {
+ HWND wndPrev = (HWND) lParam;
+ BOOL fMinimized = (BOOL) HIWORD(wParam);
+ int fActive = LOWORD(wParam);
+ BOOL inactive = WA_INACTIVE==fActive;
+ #ifdef VERBOSE_ON
+ BOOL anyActive = WA_ACTIVE==fActive, clickActive = WA_CLICKACTIVE==fActive;
+ DBG_PRINT("*** WindowsWindow: WM_ACTIVATE window %p, prev %p, minimized %d, active %d (any %d, click %d, inactive %d), FS %d\n",
+ wnd, wndPrev, fMinimized, fActive, anyActive, clickActive, inactive, wud->isFullscreen);
+ #endif
+ if( wud->isFullscreen ) {
+ // Bug 916 - NEWT Fullscreen Mode on Windows ALT-TAB doesn't allow Application Switching
+ // Remedy for 'some' display drivers, i.e. Intel HD:
+ // Explicitly push fullscreen window to BOTTOM when inactive (ALT-TAB)
+ UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if( inactive ) {
+ SetWindowPos(wnd, HWND_BOTTOM, 0, 0, 0, 0, flags);
+ } else {
+ SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, flags);
+ SetForegroundWindow(wnd); // Slightly Higher Priority
+ }
+ }
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_CHAR:
- useDefWindowProc = WmChar(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), TRUE);
- break;
-
- case WM_KEYDOWN:
-#ifdef DEBUG_KEYS
- STD_PRINT("*** WindowsWindow: windProc sending window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
-#endif
- useDefWindowProc = WmKeyDown(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SETTINGCHANGE:
+ if (wParam == SPI_SETNONCLIENTMETRICS) {
+ // make sure insets are updated, we don't need to resize the window
+ // because the size of the client area doesn't change
+ (void)UpdateInsets(env, window, wnd);
+ } else {
+ useDefWindowProc = 1;
+ }
+ break;
- case WM_KEYUP:
- useDefWindowProc = WmKeyUp(env, window, wParam,
- LOWORD(lParam), HIWORD(lParam), FALSE);
- break;
+ case WM_SIZE:
+ WmSize(env, wud, wnd, (UINT)wParam);
+ break;
- case WM_SIZE:
- WmSize(env, window, wnd, (UINT)wParam);
- break;
+ case WM_SHOWWINDOW:
+ (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
+ break;
- case WM_SETTINGCHANGE:
- if (wParam == SPI_SETNONCLIENTMETRICS) {
- // make sure insets are updated, we don't need to resize the window
- // because the size of the client area doesn't change
- (void)UpdateInsets(env, window, wnd);
- } else {
+ case WM_MOVE:
+ DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
useDefWindowProc = 1;
+ break;
+
+ case WM_PAINT: {
+ RECT r;
+ if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) {
+ // clear the whole client area and issue repaint for it, w/o looping through erase background
+ ValidateRect(wnd, NULL); // clear all!
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ } else {
+ // shall not happen ?
+ ValidateRect(wnd, NULL); // clear all!
+ }
+ // return 0 == done
+ break;
}
- break;
+ case WM_ERASEBKGND:
+ // ignore erase background
+ (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
+ res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this
+ break;
+ case WM_SETCURSOR :
+ if (0 != wud->setPointerVisible) { // Tristate, -1, 0, 1
+ BOOL visibilityChangeSuccessful;
+ if (1 == wud->setPointerVisible) {
+ visibilityChangeSuccessful = SafeShowCursor(TRUE);
+ } else /* -1 == wud->setPointerVisible */ {
+ visibilityChangeSuccessful = SafeShowCursor(FALSE);
+ }
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful);
+ wud->setPointerVisible = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( 0 != wud->setPointerAction ) {
+ if( -1 == wud->setPointerAction ) {
+ wud->setPointerHandle = wud->defPointerHandle;
+ }
+ HCURSOR preHandle = SetCursor(wud->setPointerHandle);
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon change %d: pre %p -> set %p, def %p\n",
+ wud->setPointerAction, (void*)preHandle, (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ wud->setPointerAction = 0;
+ // own signal, consumed, no further processing
+ res = 1;
+ } else if( HTCLIENT == LOWORD(lParam) ) {
+ BOOL setCur = wud->isChildWindow && wud->defPointerHandle != wud->setPointerHandle;
+ #ifdef VERBOSE_ON
+ HCURSOR cur = GetCursor();
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [1 custom-override] set %p, def %p, cur %p, isChild %d, setCur %d\n",
+ (void*)wud->setPointerHandle, (void*)wud->defPointerHandle, (void*)cur, wud->isChildWindow, setCur);
+ #endif
+ if( setCur ) {
+ SetCursor(wud->setPointerHandle);
+ // own signal, consumed, no further processing
+ res = 1;
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR PointerIcon NOP [2 parent-override] set %p, def %p\n", (void*)wud->setPointerHandle, (void*)wud->defPointerHandle);
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_SETCURSOR !HTCLIENT\n");
+ // NOP for us, allow parent to act
+ res = 0;
+ }
+ break;
- case WM_LBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SETFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam);
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
+ useDefWindowProc = 1;
+ break;
- case WM_LBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 1, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_KILLFOCUS:
+ DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p, inside %d, captured %d, tDown %d\n",
+ wnd, (HWND)wParam, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount);
+ if( wud->touchDownCount == 0 ) {
+ wud->pointerInside = 0;
+ if( wud->pointerCaptured ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ useDefWindowProc = 1;
+ } else {
+ // quick focus .. we had it already, are enabled ..
+ SetFocus(wnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
+ }
+ break;
- case WM_MBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSCHAR:
+ useDefWindowProc = 1;
+ break;
- case WM_MBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 2, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONDOWN:
- DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n");
- (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_PRESSED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_SYSKEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_SYSKEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, (USHORT)wParam, repCnt, scanCode, flags, TRUE);
+ break;
- case WM_RBUTTONUP:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_RELEASED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 3, (jint) 0);
- useDefWindowProc = 1;
- break;
+ case WM_CHAR:
+ useDefWindowProc = 1;
+ break;
+
+ case WM_KEYDOWN:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYDOWN sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyDown(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_MOUSEMOVE:
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_MOVED,
- GetModifiers(),
- (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- case WM_MOUSELEAVE:
- (*env)->CallVoidMethod(env, window, enqueueMouseEventID, JNI_FALSE,
- (jint) EVENT_MOUSE_EXITED,
- 0,
- (jint) -1, (jint) -1, // fake
- (jint) 0, (jint) 0);
- useDefWindowProc = 1;
- break;
- // Java synthesizes EVENT_MOUSE_ENTERED
-
- case WM_MOUSEWHEEL: {
- // need to convert the coordinates to component-relative
- int x = GET_X_LPARAM(lParam);
- int y = GET_Y_LPARAM(lParam);
- POINT eventPt;
- eventPt.x = x;
- eventPt.y = y;
- ScreenToClient(wnd, &eventPt);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jint) EVENT_MOUSE_WHEEL_MOVED,
- GetModifiers(),
- (jint) eventPt.x, (jint) eventPt.y,
- (jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f));
- useDefWindowProc = 1;
- break;
- }
+ case WM_KEYUP:
+ repCnt = HIWORD(lParam); scanCode = LOBYTE(repCnt); flags = HIBYTE(repCnt);
+ repCnt = LOWORD(lParam);
+ #ifdef DEBUG_KEYS
+ DBG_PRINT("*** WindowsWindow: windProc WM_KEYUP sending window %p -> %p, code 0x%X, repCnt %d, scanCode 0x%X, flags 0x%X\n", wnd, window, (int)wParam, (int)repCnt, (int)scanCode, (int)flags);
+ #endif
+ useDefWindowProc = WmKeyUp(env, window, wParam, repCnt, scanCode, flags, FALSE);
+ break;
- case WM_SETFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_KILLFOCUS:
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
- useDefWindowProc = 1;
- break;
+ case WM_LBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 < wud->touchDownLastUp ) {
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0;
+ } else if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 1, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_SHOWWINDOW:
- (*env)->CallVoidMethod(env, window, visibleChangedID, JNI_FALSE, wParam==TRUE?JNI_TRUE:JNI_FALSE);
- break;
+ case WM_MBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_MOVE:
- DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam));
- useDefWindowProc = 1;
- break;
+ case WM_MBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 2, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
- case WM_PAINT: {
- RECT r;
- useDefWindowProc = 0;
- if (GetUpdateRect(wnd, &r, TRUE /* erase background */)) {
- /*
- jint width = r.right-r.left;
- jint height = r.bottom-r.top;
- if (width > 0 && height > 0) {
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, r.left, r.top, width, height);
+ case WM_RBUTTONDOWN: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_PRESSED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
}
- ValidateRect(wnd, &r);
- */
+ break;
+
+ case WM_RBUTTONUP: {
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 0;
+ ReleaseCapture();
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_RELEASED,
+ GetModifiers( 0 ),
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 3, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ jint modifiers = GetModifiers(0);
+ if( 0 == wud->pointerCaptured && 0 != ( modifiers & EVENT_BUTTONALL_MASK ) ) {
+ wud->pointerCaptured = 1;
+ SetCapture(wnd);
+ }
+ if( 0 == wud->pointerInside ) {
+ wud->pointerInside = 1;
+ NewtWindows_trackPointerLeave(wnd);
+ SetCursor(wud->setPointerHandle);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ (jshort) 0, (jfloat) 0.0f);
+ }
+ useDefWindowProc = 1;
+ }
+ break;
+ case WM_MOUSELEAVE: {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
+ wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ wud->pointerInside = 0;
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_EXITED,
+ 0,
+ (jint) -1, (jint) -1, // fake
+ (jshort) 0, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
+ }
+ break;
+ // Java synthesizes EVENT_MOUSE_ENTERED
+
+ case WM_HSCROLL: { // Only delivered if windows has WS_HSCROLL, hence dead code!
+ int sb = LOWORD(wParam);
+ int modifiers = GetModifiers( 0 ) | EVENT_SHIFT_MASK;
+ float rotation;
+ switch(sb) {
+ case SB_LINELEFT:
+ rotation = 1.0f;
+ break;
+ case SB_PAGELEFT:
+ rotation = 2.0f;
+ break;
+ case SB_LINERIGHT:
+ rotation = -1.0f;
+ break;
+ case SB_PAGERIGHT:
+ rotation = -1.0f;
+ break;
+ }
+ DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers);
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) 0, (jint) 0,
+ (jshort) 1, (jfloat) rotation);
+ useDefWindowProc = 1;
+ break;
+ }
+ case WM_MOUSEHWHEEL: /* tilt */
+ case WM_MOUSEWHEEL: /* rotation */ {
+ // need to convert the coordinates to component-relative
+ int x = GET_X_LPARAM(lParam);
+ int y = GET_Y_LPARAM(lParam);
+ int modifiers = GetModifiers( 0 );
+ float rotationOrTilt = (float)(GET_WHEEL_DELTA_WPARAM(wParam))/WHEEL_DELTAf;
+ int vKeys = GET_KEYSTATE_WPARAM(wParam);
+ POINT eventPt;
+ eventPt.x = x;
+ eventPt.y = y;
+ ScreenToClient(wnd, &eventPt);
+
+ if( WM_MOUSEHWHEEL == message ) {
+ modifiers |= EVENT_SHIFT_MASK;
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEHWHEEL %d/%d, tilt %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ } else {
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n",
+ (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers);
+ }
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_WHEEL_MOVED,
+ modifiers,
+ (jint) eventPt.x, (jint) eventPt.y,
+ (jshort) 1, (jfloat) rotationOrTilt);
+ useDefWindowProc = 1;
+ break;
}
- break;
- }
- case WM_ERASEBKGND:
- // ignore erase background
- (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1);
- useDefWindowProc = 0;
- res = 1; // OpenGL, etc .. erases the background, hence we claim to have just done this
- break;
+ case WM_TOUCH: if( wud->supportsMTouch ) {
+ UINT cInputs = LOWORD(wParam);
+ // DBG_PRINT("*** WindowsWindow: WM_TOUCH window %p, cInputs %d\n", wnd, cInputs);
+ HTOUCHINPUT hTouch = (HTOUCHINPUT)lParam;
+ PTOUCHINPUT pInputs = (PTOUCHINPUT) calloc(cInputs, sizeof(TOUCHINPUT));
+ if (NULL != pInputs) {
+ if ( WinTouch_GetTouchInputInfo(hTouch, cInputs, pInputs, sizeof(TOUCHINPUT)) ) {
+ UINT i;
+ short eventType[cInputs];
+ jint modifiers = GetModifiers( 0 );
+ jint actionIdx = -1;
+ jint pointerNames[cInputs];
+ jint x[cInputs], y[cInputs];
+ jfloat pressure[cInputs];
+ jfloat maxPressure = 1.0F; // FIXME: n/a on windows ?
+ int allPInside = 0 < cInputs;
+ int sendFocus = 0;
+
+ for (i=0; i < cInputs; i++) {
+ PTOUCHINPUT pTi = & pInputs[i];
+ POINT eventPt;
+ int isDown = pTi->dwFlags & TOUCHEVENTF_DOWN;
+ int isUp = pTi->dwFlags & TOUCHEVENTF_UP;
+ int isMove = pTi->dwFlags & TOUCHEVENTF_MOVE;
+
+ int isPrim = pTi->dwFlags & TOUCHEVENTF_PRIMARY;
+ int isNoCoalesc = pTi->dwFlags & TOUCHEVENTF_NOCOALESCE;
+
+ #ifdef VERBOSE_ON
+ const char * touchAction;
+ if( isDown ) {
+ touchAction = "down";
+ } else if( isUp ) {
+ touchAction = "_up_";
+ } else if( isMove ) {
+ touchAction = "move";
+ } else {
+ touchAction = "undf";
+ }
+ #endif
+
+ pointerNames[i] = (jint)pTi->dwID;
+ eventPt.x = TOUCH_COORD_TO_PIXEL(pTi->x);
+ eventPt.y = TOUCH_COORD_TO_PIXEL(pTi->y);
+ ScreenToClient(wnd, &eventPt);
+
+ int pInside = 0 <= eventPt.x && 0 <= eventPt.y && eventPt.x < wud->width && eventPt.y < wud->height;
+ allPInside &= pInside;
+
+ x[i] = (jint)eventPt.x;
+ y[i] = (jint)eventPt.y;
+ pressure[i] = 1.0F; // FIXME: n/a on windows ?
+ if(isDown) {
+ sendFocus = 0 == wud->touchDownCount;
+ eventType[i] = (jshort) EVENT_MOUSE_PRESSED;
+ wud->touchDownCount++;
+ wud->touchDownLastUp = 0;
+ } else if(isUp) {
+ eventType[i] = (jshort) EVENT_MOUSE_RELEASED;
+ wud->touchDownCount--;
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0 == wud->touchDownCount;
+ } else if(isMove) {
+ eventType[i] = (jshort) EVENT_MOUSE_MOVED;
+ wud->touchDownLastUp = 0;
+ } else {
+ eventType[i] = (jshort) 0;
+ }
+ if(isPrim) {
+ actionIdx = (jint)i;
+ }
+
+ #ifdef VERBOSE_ON
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH[%d/%d].%s name 0x%x, prim %d, nocoalsc %d, %d/%d [%dx%d] inside [%d/%d], tDown [c %d, lastUp %d]\n",
+ (i+1), cInputs, touchAction, (int)(pTi->dwID), isPrim, isNoCoalesc, x[i], y[i], wud->width, wud->height,
+ pInside, allPInside, wud->touchDownCount, wud->touchDownLastUp);
+ #endif
+ }
+ wud->pointerInside = allPInside;
+ if( sendFocus ) {
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ }
+ int sentCount = 0, updownCount=0, moveCount=0;
+ // Primary first, if available!
+ if( 0 <= actionIdx ) {
+ sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ // 1 Move second ..
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED == et ) {
+ if( i != actionIdx && 0 == moveCount ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ moveCount++;
+ }
+ }
+ // Up and downs last
+ for (i=0; i < cInputs; i++) {
+ short et = eventType[i];
+ if( (jshort) EVENT_MOUSE_MOVED != et ) {
+ if( i != actionIdx ) {
+ sendTouchScreenEvent(env, window, et, modifiers, i,
+ cInputs, pointerNames, x, y, pressure, maxPressure);
+ sentCount++;
+ }
+ updownCount++;
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d, inside %d, captured %d, tDown [c %d, lastUp %d]\n",
+ cInputs, actionIdx, updownCount, moveCount, sentCount, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp);
+
+ // Message processed - close it
+ WinTouch_CloseTouchInputHandle(hTouch);
+ } else {
+ useDefWindowProc = 1;
+ }
+ free(pInputs);
+ }
+ break;
+ }
- default:
- useDefWindowProc = 1;
+ default:
+ useDefWindowProc = 1;
}
- if (useDefWindowProc)
+
+ if (useDefWindowProc) {
return DefWindowProc(wnd, message, wParam, lParam);
+ }
return res;
}
/*
- * Class: jogamp_newt_driver_windows_WindowsDisplay
+ * Class: jogamp_newt_driver_windows_DisplayDriver
* Method: DispatchMessages
* Signature: ()V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMessages0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_DisplayDriver_DispatchMessages0
(JNIEnv *env, jclass clazz)
{
int i = 0;
@@ -1028,24 +1520,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMe
// DBG_PRINT("*** WindowsWindow.DispatchMessages0: thread 0x%X - gotOne %d\n", (int)GetCurrentThreadId(), (int)gotOne);
if (gotOne) {
++i;
-#ifdef DEBUG_KEYS
- if(WM_KEYDOWN == msg.message) {
- STD_PRINT("*** WindowsWindow: DispatchMessages window %p, 0x%X %d/%d\n", msg.hwnd, msg.message, (int)LOWORD(msg.lParam), (int)HIWORD(msg.lParam));
- }
-#endif
- TranslateMessage(&msg);
+ // TranslateMessage(&msg); // No more needed: We translate V_KEY -> UTF Char manually in key up/down
DispatchMessage(&msg);
}
} while (gotOne && i < 100);
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: getOriginX0
- * Signature: (I)I
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getVirtualOriginX0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginX0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN);
@@ -1055,12 +1542,12 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: getOriginY0
- * Signature: (I)I
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getVirtualOriginY0
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualOriginY0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN);
@@ -1070,12 +1557,12 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: getWidthImpl
- * Signature: (I)I
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getVirtualWidthImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualWidthImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS) > 1) {
return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN);
@@ -1085,12 +1572,12 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImp
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: getHeightImpl
- * Signature: (I)I
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getVirtualHeightImpl
+ * Signature: ()I
*/
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getHeightImpl0
- (JNIEnv *env, jobject obj, jint scrn_idx)
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getVirtualHeightImpl0
+ (JNIEnv *env, jobject obj)
{
if( GetSystemMetrics( SM_CMONITORS ) > 1) {
return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN);
@@ -1142,65 +1629,137 @@ static int NewtScreen_RotationNewtCCW2NativeCCW(JNIEnv *env, jint newt) {
return native;
}
-/*
-static void NewtScreen_scanDisplayDevices() {
- DISPLAY_DEVICE device;
- int i = 0;
- LPCTSTR name;
- while(NULL != (name = NewtScreen_getDisplayDeviceName(&device, i))) {
- fprintf(stderr, "*** [%d]: <%s> active %d\n", i, name, ( 0 != ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
- i++;
+static LPCTSTR NewtScreen_getAdapterName(DISPLAY_DEVICE * device, int crt_idx) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( FALSE == EnumDisplayDevices(NULL, crt_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getAdapterName.EnumDisplayDevices(crt_idx %d) -> FALSE\n", crt_idx);
+ return NULL;
}
-}*/
-static LPCTSTR NewtScreen_getDisplayDeviceName(DISPLAY_DEVICE * device, int scrn_idx) {
- device->cb = sizeof(DISPLAY_DEVICE);
- if( FALSE == EnumDisplayDevices(NULL, scrn_idx, device, 0) ) {
- DBG_PRINT("*** WindowsWindow: getDisplayDeviceName.EnumDisplayDevices(scrn_idx %d) -> FALSE\n", scrn_idx);
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
- if( 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
- DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(scrn_idx %d)\n", scrn_idx);
+ return device->DeviceName;
+}
+
+static LPCTSTR NewtScreen_getMonitorName(LPCTSTR adapterName, DISPLAY_DEVICE * device, int monitor_idx, BOOL onlyActive) {
+ memset(device, 0, sizeof(DISPLAY_DEVICE));
+ device->cb = sizeof(DISPLAY_DEVICE);
+ if( 0 == monitor_idx ) {
+ if( FALSE == EnumDisplayDevices(adapterName, monitor_idx, device, 0) ) {
+ DBG_PRINT("*** WindowsWindow: getDisplayName.EnumDisplayDevices(monitor_idx %d).adapter -> FALSE\n", monitor_idx);
+ return NULL;
+ }
+ }
+
+ if( onlyActive && 0 == ( device->StateFlags & DISPLAY_DEVICE_ACTIVE ) ) {
+ DBG_PRINT("*** WindowsWindow: !DISPLAY_DEVICE_ACTIVE(monitor_idx %d).display\n", monitor_idx);
+ return NULL;
+ }
+ if( NULL == device->DeviceName || 0 == _tcslen(device->DeviceName) ) {
return NULL;
}
return device->DeviceName;
}
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_dumpMonitorInfo0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPLAY_DEVICE aDevice, dDevice;
+ int i = 0, j;
+ LPCTSTR aName, dName;
+ while(NULL != (aName = NewtScreen_getAdapterName(&aDevice, i))) {
+ fprintf(stderr, "*** [%d]: <%s> flags 0x%X active %d\n", i, aName, aDevice.StateFlags, ( 0 != ( aDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j=0;
+ while(NULL != (dName = NewtScreen_getMonitorName(aName, &dDevice, j, FALSE))) {
+ fprintf(stderr, "*** [%d][%d]: <%s> flags 0x%X active %d\n", i, j, dName, dDevice.StateFlags, ( 0 != ( dDevice.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) );
+ j++;
+ }
+ i++;
+ }
+}
+
static HDC NewtScreen_createDisplayDC(LPCTSTR displayDeviceName) {
return CreateDC("DISPLAY", displayDeviceName, NULL, NULL);
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: getScreenMode0
- * Signature: (II)[I
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getAdapterName0
+ * Signature: (I)Ljava/lang/String;
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getAdapterName0
+ (JNIEnv *env, jobject obj, jint crt_idx)
{
DISPLAY_DEVICE device;
- int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
- return (*env)->NewIntArray(env, 0);
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&device, crt_idx);
+ DBG_PRINT("*** WindowsWindow: getAdapterName(crt_idx %d) -> %s, active %d\n", crt_idx,
+ (NULL==adapterName?"nil":adapterName), 0 == ( device.StateFlags & DISPLAY_DEVICE_ACTIVE ));
+ if(NULL == adapterName) {
+ return NULL;
+ }
+#ifdef UNICODE
+ return (*env)->NewString(env, adapterName, wcslen(adapterName));
+#else
+ return (*env)->NewStringUTF(env, adapterName);
+#endif
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getActiveMonitorName0
+ * Signature: (Ljava/lang/String;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getActiveMonitorName0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR monitorName;
+#ifdef UNICODE
+ LPCTSTR adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ free((void*) adapterName);
+#else
+ LPCTSTR adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+ monitorName = NewtScreen_getMonitorName(adapterName, &device, monitor_idx, TRUE);
+ DBG_PRINT("*** WindowsWindow: getMonitorName(%s, monitor_idx %d) -> %s\n", adapterName, monitor_idx, (NULL==monitorName?"nil":monitorName));
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if(NULL == monitorName) {
+ return NULL;
}
+#ifdef UNICODE
+ return (*env)->NewString(env, monitorName, wcslen(monitorName));
+#else
+ return (*env)->NewStringUTF(env, monitorName);
+#endif
+}
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (Ljava/lang/String;I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint mode_idx)
+{
+ DISPLAY_DEVICE device;
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
int devModeID;
- int widthmm, heightmm;
if(-1 < mode_idx) {
- // only at initialization time, where index >= 0
- HDC hdc = NewtScreen_createDisplayDC(deviceName);
- widthmm = GetDeviceCaps(hdc, HORZSIZE);
- heightmm = GetDeviceCaps(hdc, VERTSIZE);
- DeleteDC(hdc);
devModeID = (int) mode_idx;
- prop_num++; // add 1st extra prop, mode_idx
} else {
- widthmm = 0;
- heightmm = 0;
devModeID = ENUM_CURRENT_SETTINGS;
}
@@ -1208,11 +1767,18 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getScr
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
- if (0 == EnumDisplaySettingsEx(deviceName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE)) {
- DBG_PRINT("*** WindowsWindow: getScreenMode.EnumDisplaySettingsEx(mode_idx %d/%d) -> NULL\n", mode_idx, devModeID);
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, ( ENUM_CURRENT_SETTINGS == devModeID ) ? 0 : EDS_ROTATEDMODE);
+ DBG_PRINT("*** WindowsWindow: getMonitorMode.EnumDisplaySettingsEx(%s, mode_idx %d/%d) -> %d\n", adapterName, mode_idx, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+
+ if (0 == res) {
return (*env)->NewIntArray(env, 0);
}
-
+
// swap width and height, since Windows reflects rotated dimension, we don't
if (DMDO_90 == dm.dmDisplayOrientation || DMDO_270 == dm.dmDisplayOrientation) {
int tempWidth = dm.dmPelsWidth;
@@ -1220,43 +1786,110 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getScr
dm.dmPelsHeight = tempWidth;
}
- jint prop[ prop_num ];
+ int flags = 0;
+ if( 0 != ( dm.dmDisplayFlags & DM_INTERLACED ) ) {
+ flags |= FLAG_INTERLACE;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
int propIndex = 0;
- if( -1 < mode_idx ) {
- prop[propIndex++] = mode_idx;
- }
- prop[propIndex++] = 0; // set later for verification of iterator
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
prop[propIndex++] = dm.dmPelsWidth;
prop[propIndex++] = dm.dmPelsHeight;
prop[propIndex++] = dm.dmBitsPerPel;
- prop[propIndex++] = widthmm;
- prop[propIndex++] = heightmm;
- prop[propIndex++] = dm.dmDisplayFrequency;
+ prop[propIndex++] = dm.dmDisplayFrequency * 100; // Hz*100
+ prop[propIndex++] = flags;
+ prop[propIndex++] = 0; // not bound to id
prop[propIndex++] = NewtScreen_RotationNativeCCW2NewtCCW(env, dm.dmDisplayOrientation);
- prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
- jintArray properties = (*env)->NewIntArray(env, prop_num);
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num);
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
}
- (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop);
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
return properties;
}
/*
- * Class: jogamp_newt_driver_windows_WindowsScreen
- * Method: setScreenMode0
- * Signature: (IIIIII)Z
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: getMonitorDevice0
+ * Signature: (Ljava/lang/String;I)[I
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_setScreenMode0
- (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jint rate, jint rot)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_getMonitorDevice0
+ (JNIEnv *env, jobject obj, jstring jAdapterName, jint monitor_idx)
{
DISPLAY_DEVICE device;
- LPCTSTR deviceName = NewtScreen_getDisplayDeviceName(&device, scrn_idx);
- if(NULL == deviceName) {
- DBG_PRINT("*** WindowsWindow: setScreenMode.getDisplayDeviceName(scrn_idx %d) -> NULL\n", scrn_idx);
+ LPCTSTR adapterName;
+ {
+#ifdef UNICODE
+ adapterName = NewtCommon_GetNullTerminatedStringChars(env, jAdapterName);
+#else
+ adapterName = (*env)->GetStringUTFChars(env, jAdapterName, NULL);
+#endif
+ }
+
+ HDC hdc = NewtScreen_createDisplayDC(adapterName);
+ int widthmm = GetDeviceCaps(hdc, HORZSIZE);
+ int heightmm = GetDeviceCaps(hdc, VERTSIZE);
+ DeleteDC(hdc);
+ int devModeID = ENUM_CURRENT_SETTINGS;
+
+ DEVMODE dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ int res = EnumDisplaySettingsEx(adapterName, devModeID, &dm, 0);
+ DBG_PRINT("*** WindowsWindow: getMonitorDevice.EnumDisplaySettingsEx(%s, devModeID %d) -> %d\n", adapterName, devModeID, res);
+#ifdef UNICODE
+ free((void*) adapterName);
+#else
+ (*env)->ReleaseStringUTFChars(env, jAdapterName, adapterName);
+#endif
+ if (0 == res) {
+ return (*env)->NewIntArray(env, 0);
+ }
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = monitor_idx;
+ prop[propIndex++] = widthmm;
+ prop[propIndex++] = heightmm;
+ prop[propIndex++] = dm.dmPosition.x; // rotated viewport
+ prop[propIndex++] = dm.dmPosition.y; // rotated viewport
+ prop[propIndex++] = dm.dmPelsWidth; // rotated viewport
+ prop[propIndex++] = dm.dmPelsHeight; // rotated viewport
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_windows_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (IIIIIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint monitor_idx, jint x, jint y, jint width, jint height, jint bits, jint rate, jint flags, jint rot)
+{
+ DISPLAY_DEVICE adapterDevice, monitorDevice;
+ LPCTSTR adapterName = NewtScreen_getAdapterName(&adapterDevice, monitor_idx);
+ if(NULL == adapterName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getAdapterName(monitor_idx %d) -> NULL\n", monitor_idx);
+ return JNI_FALSE;
+ }
+ LPCTSTR monitorName = NewtScreen_getMonitorName(adapterName, &monitorDevice, 0, TRUE);
+ if(NULL == monitorName) {
+ DBG_PRINT("*** WindowsWindow: setMonitorMode.getMonitorName(monitor_idx 0) -> NULL\n");
return JNI_FALSE;
}
@@ -1264,10 +1897,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_setScre
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
+ if( 0 <= x && 0 <= y ) {
+ dm.dmPosition.x = (int)x;
+ dm.dmPosition.y = (int)y;
+ }
dm.dmPelsWidth = (int)width;
dm.dmPelsHeight = (int)height;
dm.dmBitsPerPel = (int)bits;
dm.dmDisplayFrequency = (int)rate;
+ if( 0 != ( flags & FLAG_INTERLACE ) ) {
+ dm.dmDisplayFlags |= DM_INTERLACED;
+ }
dm.dmDisplayOrientation = NewtScreen_RotationNewtCCW2NativeCCW(env, rot);
// swap width and height, since Windows reflects rotated dimension, we don't
@@ -1277,18 +1917,21 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_setScre
dm.dmPelsHeight = tempWidth;
}
- dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+ dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
+ if( 0 <= x && 0 <= y ) {
+ dm.dmFields |= DM_POSITION;
+ }
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, 0) ) ? JNI_TRUE : JNI_FALSE ;
+ return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(adapterName, &dm, NULL, 0, NULL) ) ? JNI_TRUE : JNI_FALSE ;
}
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: initIDs0
* Signature: ()Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs0
- (JNIEnv *env, jclass clazz)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0
+ (JNIEnv *env, jclass clazz, jlong hInstance)
{
NewtCommon_init(env);
@@ -1299,10 +1942,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs
visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V");
+ sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V");
requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
if (insetsChangedID == NULL ||
@@ -1312,23 +1954,39 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs
visibleChangedID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
+ sendTouchScreenEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
}
- BuildDynamicKeyMapTable();
+ InitKeyMapTableScanCode(env);
+
+ {
+ HANDLE shell = LoadLibrary(TEXT("user32.dll"));
+ if (shell) {
+ WinTouch_CloseTouchInputHandle = (CloseTouchInputHandlePROCADDR) GetProcAddressA(shell, "CloseTouchInputHandle");
+ WinTouch_GetTouchInputInfo = (GetTouchInputInfoPROCADDR) GetProcAddressA(shell, "GetTouchInputInfo");
+ WinTouch_IsTouchWindow = (IsTouchWindowPROCADDR) GetProcAddressA(shell, "IsTouchWindow");
+ WinTouch_RegisterTouchWindow = (RegisterTouchWindowPROCADDR) GetProcAddressA(shell, "RegisterTouchWindow");
+ WinTouch_UnregisterTouchWindow = (UnregisterTouchWindowPROCADDR) GetProcAddressA(shell, "UnregisterTouchWindow");
+ if(NULL != WinTouch_CloseTouchInputHandle && NULL != WinTouch_GetTouchInputInfo &&
+ NULL != WinTouch_IsTouchWindow && NULL != WinTouch_RegisterTouchWindow && NULL != WinTouch_UnregisterTouchWindow) {
+ WinTouch_func_avail = 1;
+ } else {
+ WinTouch_func_avail = 0;
+ }
+ }
+ }
return JNI_TRUE;
}
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: getNewtWndProc0
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_getNewtWndProc0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_getNewtWndProc0
(JNIEnv *env, jclass clazz)
{
return (jlong) (intptr_t) wndProc;
@@ -1365,20 +2023,21 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible,
UpdateWindow(hwnd);
}
+#define WS_DEFAULT_STYLES (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP)
+
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: CreateWindow
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWindow0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj,
- jlong hInstance, jstring jWndClassName, jstring jWndName,
- jlong parent,
- jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
+ jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor,
+ jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags)
{
HWND parentWindow = (HWND) (intptr_t) parent;
const TCHAR* wndClassName = NULL;
const TCHAR* wndName = NULL;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_TABSTOP;
+ DWORD windowStyle = WS_DEFAULT_STYLES | WS_VISIBLE;
int x=(int)jx, y=(int)jy;
int width=(int)defaultWidth, height=(int)defaultHeight;
HWND window = NULL;
@@ -1415,8 +2074,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
(HINSTANCE) (intptr_t) hInstance,
NULL);
- DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
- (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height,
+ DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n",
+ (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height,
TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition);
if (NULL == window) {
@@ -1427,6 +2086,31 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData));
wud->jinstance = (*env)->NewGlobalRef(env, obj);
wud->jenv = env;
+ wud->width = width;
+ wud->height = height;
+ wud->setPointerVisible = 0;
+ wud->setPointerAction = 0;
+ wud->defPointerHandle = LoadCursor( NULL, IDC_ARROW);
+ wud->setPointerHandle = wud->defPointerHandle;
+ wud->isFullscreen = 0;
+ wud->isChildWindow = NULL!=parentWindow;
+ wud->pointerCaptured = 0;
+ wud->pointerInside = 0;
+ wud->touchDownCount = 0;
+ wud->touchDownLastUp = 0;
+ wud->supportsMTouch = 0;
+ if ( WinTouch_func_avail && winMajor > 6 || ( winMajor == 6 && winMinor >= 1 ) ) {
+ int value = GetSystemMetrics(SM_DIGITIZER);
+ if (value & NID_READY) { /* ready */
+ if (value & NID_MULTI_INPUT) { /* multitouch */
+ wud->supportsMTouch = 1;
+ }
+ if (value & NID_INTEGRATED_TOUCH) { /* Integrated touch */
+ }
+ }
+ }
+ DBG_PRINT("*** WindowsWindow: CreateWindow winTouchFuncAvail %d, supportsMTouch %d\n", WinTouch_func_avail, wud->supportsMTouch);
+
#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
SetWindowLong(window, GWL_USERDATA, (intptr_t) wud);
#else
@@ -1459,6 +2143,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
NewtWindow_setVisiblePosSize(window, TST_FLAG_IS_ALWAYSONTOP(flags), TRUE, x, y, width, height);
}
+ if( wud->supportsMTouch ) {
+ WinTouch_RegisterTouchWindow(window, 0);
+ }
}
#ifdef UNICODE
@@ -1469,15 +2156,21 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind
(*env)->ReleaseStringUTFChars(env, jWndName, wndName);
#endif
+#ifdef TEST_MOUSE_HOOKS
+ hookLLMP = SetWindowsHookEx(WH_MOUSE_LL, &HookLowLevelMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ hookMP = SetWindowsHookEx(WH_MOUSE_LL, &HookMouseProc, (HINSTANCE) (intptr_t) hInstance, 0);
+ DBG_PRINT("**** LLMP Hook %p, MP Hook %p\n", hookLLMP, hookMP);
+#endif
+
return (jlong) (intptr_t) window;
}
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: MonitorFromWindow
* Signature: (J)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_MonitorFromWindow0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_MonitorFromWindow0
(JNIEnv *env, jobject obj, jlong window)
{
#if (_WIN32_WINNT >= 0x0500 || _WIN32_WINDOWS >= 0x0410 || WINVER >= 0x0500) && !defined(_WIN32_WCE)
@@ -1487,45 +2180,34 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_MonitorFro
#endif
}
-static jboolean NewtWindows_setFullScreen(jboolean fullscreen)
-{
- int flags = 0;
- DEVMODE dm;
- // initialize the DEVMODE structure
- ZeroMemory(&dm, sizeof(dm));
- dm.dmSize = sizeof(dm);
-
- if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm))
- {
- return JNI_FALSE;
- }
-
- flags = ( JNI_TRUE == fullscreen ) ? CDS_FULLSCREEN : CDS_RESET ;
-
- return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE;
-}
-
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: reconfigureWindow0
* Signature: (JJIIIII)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigureWindow0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureWindow0
(JNIEnv *env, jobject obj, jlong parent, jlong window,
jint x, jint y, jint width, jint height, jint flags)
{
HWND hwndP = (HWND) (intptr_t) parent;
HWND hwnd = (HWND) (intptr_t) window;
- DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ;
+ DWORD windowStyle = WS_DEFAULT_STYLES;
BOOL styleChange = TST_FLAG_CHANGE_DECORATION(flags) || TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ;
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+
- DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d\n",
+ DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n",
parent, window, x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), styleChange, wud->isChildWindow, wud->isFullscreen);
if (!IsWindow(hwnd)) {
DBG_PRINT("*** WindowsWindow: reconfigureWindow0 failure: Passed window %p is invalid\n", (void*)hwnd);
@@ -1537,6 +2219,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure
return;
}
+ wud->isChildWindow = NULL != hwndP;
+
if(TST_FLAG_IS_VISIBLE(flags)) {
windowStyle |= WS_VISIBLE ;
}
@@ -1547,11 +2231,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure
//
if( TST_FLAG_CHANGE_PARENTING(flags) && NULL == hwndP ) {
// TOP: in -> out
+
+ // HIDE to allow setting ICONs (Windows bug?) .. WS_VISIBLE (style) will reset visibility
+ ShowWindow(hwnd, SW_HIDE);
+
SetParent(hwnd, NULL);
}
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) { // FS on
// TOP: in -> out
+ wud->isFullscreen = 1;
NewtWindows_setFullScreen(JNI_TRUE);
}
@@ -1569,6 +2258,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure
if( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off
// CHILD: out -> in
+ wud->isFullscreen = 0;
NewtWindows_setFullScreen(JNI_FALSE);
}
@@ -1587,15 +2277,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_reconfigure
}
}
- DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X\n");
+ DBG_PRINT("*** WindowsWindow: reconfigureWindow0.X isChild %d, isFullscreen %d\n", wud->isChildWindow, wud->isFullscreen);
}
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: setTitle
* Signature: (JLjava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setTitle0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setTitle0
(JNIEnv *env, jclass clazz, jlong window, jstring title)
{
HWND hwnd = (HWND) (intptr_t) window;
@@ -1609,11 +2299,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setTitle0
}
/*
- * Class: jogamp_newt_driver_windows_WindowsWindow
+ * Class: jogamp_newt_driver_windows_WindowDriver
* Method: requestFocus
* Signature: (JZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_requestFocus0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_requestFocus0
(JNIEnv *env, jobject obj, jlong window, jboolean force)
{
DBG_PRINT("*** WindowsWindow: RequestFocus0\n");
@@ -1621,62 +2311,41 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_requestFocu
}
/*
- * Class: Java_jogamp_newt_driver_windows_WindowsWindow
+ * Class: Java_jogamp_newt_driver_windows_WindowDriver
* Method: setPointerVisible0
* Signature: (JJZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_setPointerVisible0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_setPointerVisible0
(JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible)
{
HWND hwnd = (HWND) (intptr_t) window;
- int res, resOld, i;
- jboolean b;
-
- if(JNI_TRUE == mouseVisible) {
- res = ShowCursor(TRUE);
- if(res < 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(TRUE);
- } while(res!=resOld && res<0 && ++i<10);
- }
- b = res>=0 ? JNI_TRUE : JNI_FALSE;
- } else {
- res = ShowCursor(FALSE);
- if(res >= 0) {
- i=0;
- do {
- resOld = res;
- res = ShowCursor(FALSE);
- } while(res!=resOld && res>=0 && ++i<10);
- }
- b = res<0 ? JNI_TRUE : JNI_FALSE;
- }
-
- DBG_PRINT( "*** WindowsWindow: setPointerVisible0: %d, res %d/%d\n", mouseVisible, res, b);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerVisible = mouseVisible ? 1 : -1;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
- return b;
+ return JNI_TRUE;
}
/*
- * Class: Java_jogamp_newt_driver_windows_WindowsWindow
+ * Class: Java_jogamp_newt_driver_windows_WindowDriver
* Method: confinePointer0
* Signature: (JJZIIII)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_confinePointer0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_confinePointer0
(JNIEnv *env, jclass clazz, jlong window, jboolean confine, jint l, jint t, jint r, jint b)
{
HWND hwnd = (HWND) (intptr_t) window;
jboolean res;
if(JNI_TRUE == confine) {
- // SetCapture(hwnd);
- // res = ( GetCapture() == hwnd ) ? JNI_TRUE : JNI_FALSE;
RECT rect = { l, t, r, b };
res = ClipCursor(&rect) ? JNI_TRUE : JNI_FALSE;
} else {
- // res = ReleaseCapture() ? JNI_TRUE : JNI_FALSE;
res = ClipCursor(NULL) ? JNI_TRUE : JNI_FALSE;
}
DBG_PRINT( "*** WindowsWindow: confinePointer0: %d, [ l %d t %d r %d b %d ], res %d\n",
@@ -1686,27 +2355,104 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_confine
}
/*
- * Class: Java_jogamp_newt_driver_windows_WindowsWindow
+ * Class: Java_jogamp_newt_driver_windows_WindowDriver
* Method: warpPointer0
* Signature: (JJII)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_warpPointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong window, jint x, jint y)
{
DBG_PRINT( "*** WindowsWindow: warpPointer0: %d/%d\n", x, y);
SetCursorPos(x, y);
}
-/*
- * Class: Java_jogamp_newt_driver_windows_WindowsWindow
- * Method: trackPointerLeave0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_trackPointerLeave0
- (JNIEnv *env, jclass clazz, jlong window)
-{
+JNIEXPORT jlong JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused,
+ jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
+
+ if( 0 == pixels ) {
+ return 0;
+ }
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ const int bytes = 4 * width * height; // BGRA8888
+
+ DWORD dwWidth, dwHeight;
+ BITMAPV5HEADER bi;
+ HBITMAP hBitmap;
+ void *lpBits;
+ HICON handle = NULL;
+
+ dwWidth = width; // width of cursor
+ dwHeight = height; // height of cursor
+
+ ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
+ bi.bV5Size = sizeof(BITMAPV5HEADER);
+ bi.bV5Width = dwWidth;
+ bi.bV5Height = -1 * dwHeight;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ // The following mask specification specifies a supported 32 BPP
+ // alpha format for Windows XP.
+ bi.bV5RedMask = 0x00FF0000;
+ bi.bV5GreenMask = 0x0000FF00;
+ bi.bV5BlueMask = 0x000000FF;
+ bi.bV5AlphaMask = 0xFF000000;
+
+ HDC hdc;
+ hdc = GetDC(NULL);
+
+ // Create the DIB section with an alpha channel.
+ hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+ (void **)&lpBits, NULL, (DWORD)0);
+
+ memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes);
+
+ ReleaseDC(NULL,hdc);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ // Create an empty mask bitmap.
+ HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);
+
+ ICONINFO ii;
+ ii.fIcon = isCursor ? FALSE : TRUE;
+ ii.xHotspot = hotX;
+ ii.yHotspot = hotY;
+ ii.hbmMask = hMonoBitmap;
+ ii.hbmColor = hBitmap;
+
+ // Create the alpha cursor with the alpha DIB section.
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(hBitmap);
+ DeleteObject(hMonoBitmap);
+
+ return (jlong) (intptr_t) handle;
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_DisplayDriver_destroyIcon0(JNIEnv *env, jobject _unused, jlong jhandle) {
+ HICON handle = (HICON) (intptr_t) jhandle;
+ DestroyIcon(handle);
+}
+
+JNIEXPORT void JNICALL
+Java_jogamp_newt_driver_windows_WindowDriver_setPointerIcon0(JNIEnv *env, jobject _unused, jlong window, jlong iconHandle) {
HWND hwnd = (HWND) (intptr_t) window;
- DBG_PRINT( "*** WindowsWindow: trackMouseLeave0\n");
- NewtWindows_trackPointerLeave(hwnd);
+ WindowUserData * wud;
+#if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 )
+ wud = (WindowUserData *) GetWindowLong(hwnd, GWL_USERDATA);
+#else
+ wud = (WindowUserData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#endif
+ wud->setPointerAction = 0 != iconHandle ? 1 : -1;
+ wud->setPointerHandle = (HCURSOR) (intptr_t) iconHandle;
+ SendMessage(hwnd, WM_SETCURSOR, 0, 0);
}
diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h
index cefef690f..e58cdb755 100644
--- a/src/newt/native/X11Common.h
+++ b/src/newt/native/X11Common.h
@@ -45,9 +45,11 @@
#include <X11/extensions/Xrandr.h>
-#include "jogamp_newt_driver_x11_X11Screen.h"
-#include "jogamp_newt_driver_x11_X11Display.h"
-#include "jogamp_newt_driver_x11_X11Window.h"
+#include "jogamp_newt_driver_x11_DisplayDriver.h"
+#include "jogamp_newt_driver_x11_ScreenDriver.h"
+#include "jogamp_newt_driver_x11_RandR11.h"
+#include "jogamp_newt_driver_x11_RandR13.h"
+#include "jogamp_newt_driver_x11_WindowDriver.h"
#include "Window.h"
#include "MouseEvent.h"
@@ -72,7 +74,6 @@ extern jmethodID visibleChangedID;
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
-void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env);
Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 88ac0df7e..b62a9b234 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -28,97 +28,55 @@
#include "X11Common.h"
-#define USE_SENDIO_DIRECT 1
+#include <X11/Xcursor/Xcursor.h>
+
+// #include <X11/XKBlib.h> // XKB disabled for now
jclass X11NewtWindowClazz = NULL;
jmethodID insetsChangedID = NULL;
jmethodID visibleChangedID = NULL;
-static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/X11Window";
+static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver";
static jmethodID displayCompletedID = NULL;
+static jmethodID getCurrentThreadNameID = NULL;
+static jmethodID dumpStackID = NULL;
static jmethodID sizeChangedID = NULL;
static jmethodID positionChangedID = NULL;
static jmethodID focusChangedID = NULL;
static jmethodID reparentNotifyID = NULL;
static jmethodID windowDestroyNotifyID = NULL;
static jmethodID windowRepaintID = NULL;
-static jmethodID enqueueMouseEventID = NULL;
static jmethodID sendMouseEventID = NULL;
-static jmethodID enqueueKeyEventID = NULL;
static jmethodID sendKeyEventID = NULL;
static jmethodID requestFocusID = NULL;
-static JavaVM *jvmHandle = NULL;
-static int jvmVersion = 0;
-
-static void setupJVMVars(JNIEnv * env) {
- if(0 != (*env)->GetJavaVM(env, &jvmHandle)) {
- jvmHandle = NULL;
- }
- jvmVersion = (*env)->GetVersion(env);
-}
-
-static XErrorHandler origErrorHandler = NULL ;
-
-static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e)
-{
- fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno));
-
- if (e->error_code == BadAtom) {
- fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid);
- } else if (e->error_code == BadWindow) {
- fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid);
- } else {
- int shallBeDetached = 0;
- JNIEnv *jniEnv = NULL;
- const char * errStr = strerror(errno);
-
- fprintf(stderr, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr);
-
- jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
- if(NULL==jniEnv) {
- fprintf(stderr, "NEWT X11 Error: null JNIEnv");
- return;
- }
-
- NewtCommon_throwNewRuntimeException(jniEnv, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s",
- dpy, e->error_code, errStr);
-
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
- }
-
- return 0;
-}
-
-void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) {
- if(onoff) {
- if(NULL==origErrorHandler) {
- setupJVMVars(env);
- origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler);
- }
- } else {
- if(NULL!=origErrorHandler) {
- XSetErrorHandler(origErrorHandler);
- origErrorHandler = NULL;
- }
- }
-}
-
/**
* Keycode
*/
+// #define DEBUG_KEYS 1
+
#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b))
-static jint X11KeySym2NewtVKey(KeySym keySym) {
- if(IS_WITHIN(keySym,XK_F1,XK_F12))
- return (keySym-XK_F1)+J_VK_F1;
- if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9))
- return (keySym-XK_KP_0)+J_VK_NUMPAD0;
+/**
+ * QT Reference:
+ * <http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qkeymapper_x11.cpp#line879>
+ */
+static short X11KeySym2NewtVKey(KeySym keySym) {
+ if( IS_WITHIN( keySym, XK_a, XK_z ) ) {
+ return ( keySym - XK_a ) + J_VK_A ;
+ }
+ if( IS_WITHIN( keySym, XK_0, XK_9 ) ) {
+ return ( keySym - XK_0 ) + J_VK_0 ;
+ }
+ if( IS_WITHIN( keySym, XK_KP_0, XK_KP_9 ) ) {
+ return ( keySym - XK_KP_0 ) + J_VK_NUMPAD0 ;
+ }
+ if( IS_WITHIN( keySym, XK_F1, XK_F12 ) ) {
+ return ( keySym - XK_F1 ) + J_VK_F1 ;
+ }
switch(keySym) {
case XK_Return:
@@ -132,8 +90,6 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_TAB;
case XK_Cancel:
return J_VK_CANCEL;
- case XK_Clear:
- return J_VK_CLEAR;
case XK_Shift_L:
case XK_Shift_R:
return J_VK_SHIFT;
@@ -141,8 +97,15 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_Control_R:
return J_VK_CONTROL;
case XK_Alt_L:
- case XK_Alt_R:
return J_VK_ALT;
+ case XK_Alt_R:
+ case XK_ISO_Level3_Shift:
+ return J_VK_ALT_GRAPH;
+ case XK_Super_L:
+ case XK_Super_R:
+ return J_VK_WINDOWS;
+ case XK_Menu:
+ return J_VK_CONTEXT_MENU;
case XK_Pause:
return J_VK_PAUSE;
case XK_Caps_Lock:
@@ -161,6 +124,10 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
case XK_End:
case XK_KP_End:
return J_VK_END;
+ case XK_Begin:
+ return J_VK_BEGIN;
+ case XK_KP_Begin: // NumPad 5 - equal behavior w/ QT/Windows
+ return J_VK_CLEAR;
case XK_Home:
case XK_KP_Home:
return J_VK_HOME;
@@ -188,6 +155,7 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_DECIMAL;
case XK_KP_Divide:
return J_VK_DIVIDE;
+ case XK_Clear: // equal behavior w/ QT
case XK_Delete:
case XK_KP_Delete:
return J_VK_DELETE;
@@ -202,28 +170,43 @@ static jint X11KeySym2NewtVKey(KeySym keySym) {
return J_VK_INSERT;
case XK_Help:
return J_VK_HELP;
+ case XK_grave:
+ return J_VK_BACK_QUOTE;
+ case XK_apostrophe:
+ return J_VK_QUOTE;
}
return keySym;
}
-static jint X11InputState2NewtModifiers(unsigned int xstate) {
+#define ShiftCtrlModMask ( ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask )
+
+static jboolean altGraphDown = JNI_FALSE;
+
+static jint X11InputState2NewtModifiers(unsigned int xstate, jshort javaVKey, jboolean keyDown) {
jint modifiers = 0;
- if ((ControlMask & xstate) != 0) {
+ if ( (ControlMask & xstate) != 0 || J_VK_CONTROL == javaVKey ) {
modifiers |= EVENT_CTRL_MASK;
}
- if ((ShiftMask & xstate) != 0) {
+ if ( (ShiftMask & xstate) != 0 || J_VK_SHIFT == javaVKey ) {
modifiers |= EVENT_SHIFT_MASK;
}
- if ((Mod1Mask & xstate) != 0) {
+ if ( J_VK_ALT == javaVKey ) {
+ altGraphDown = JNI_FALSE;
modifiers |= EVENT_ALT_MASK;
+ } else if ( (short)J_VK_ALT_GRAPH == javaVKey ) {
+ altGraphDown = keyDown;
+ modifiers |= EVENT_ALT_GRAPH_MASK;
+ } else if ( (Mod1Mask & xstate) != 0 ) {
+ // XK_Alt_L or XK_Alt_R
+ modifiers |= altGraphDown ? EVENT_ALT_GRAPH_MASK : EVENT_ALT_MASK;
}
- if ((Button1Mask & xstate) != 0) {
+ if ( (Button1Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON1_MASK;
}
- if ((Button2Mask & xstate) != 0) {
+ if ( (Button2Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON2_MASK;
}
- if ((Button3Mask & xstate) != 0) {
+ if ( (Button3Mask & xstate) != 0 ) {
modifiers |= EVENT_BUTTON3_MASK;
}
@@ -236,12 +219,12 @@ static jint X11InputState2NewtModifiers(unsigned int xstate) {
*/
/*
- * Class: jogamp_newt_driver_x11_X11Display
+ * Class: jogamp_newt_driver_x11_DisplayDriver
* Method: initIDs
* Signature: (Z)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
- (JNIEnv *env, jclass clazz)
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
+ (JNIEnv *env, jclass clazz, jboolean debug)
{
jclass c;
@@ -250,16 +233,19 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
if(NULL==X11NewtWindowClazz) {
c = (*env)->FindClass(env, ClazzNameX11NewtWindow);
if(NULL==c) {
- NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameX11NewtWindow);
+ NewtCommon_FatalError(env, "NEWT X11Display: can't find %s", ClazzNameX11NewtWindow);
}
X11NewtWindowClazz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==X11NewtWindowClazz) {
- NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameX11NewtWindow);
+ NewtCommon_FatalError(env, "NEWT X11Display: can't use %s", ClazzNameX11NewtWindow);
}
}
+ // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJ)V"); // Variant using XKB
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
+ getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;");
+ dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V");
insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V");
sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V");
positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V");
@@ -268,13 +254,13 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
- enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V");
- sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V");
- enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V");
- sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V");
+ sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V");
+ sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V");
requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V");
if (displayCompletedID == NULL ||
+ getCurrentThreadNameID == NULL ||
+ dumpStackID == NULL ||
insetsChangedID == NULL ||
sizeChangedID == NULL ||
positionChangedID == NULL ||
@@ -283,9 +269,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
reparentNotifyID == NULL ||
windowDestroyNotifyID == NULL ||
windowRepaintID == NULL ||
- enqueueMouseEventID == NULL ||
sendMouseEventID == NULL ||
- enqueueKeyEventID == NULL ||
sendKeyEventID == NULL ||
requestFocusID == NULL) {
return JNI_FALSE;
@@ -296,16 +280,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0
}
/*
- * Class: jogamp_newt_driver_x11_X11Display
+ * Class: jogamp_newt_driver_x11_DisplayDriver
* Method: CompleteDisplay
* Signature: (J)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_CompleteDisplay0
(JNIEnv *env, jobject obj, jlong display)
{
Display * dpy = (Display *)(intptr_t)display;
jlong javaObjectAtom;
jlong windowDeleteAtom;
+ // jlong kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -324,23 +309,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0
}
// XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+ // kbdHandle = (jlong) (intptr_t) XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); // XKB disabled for now
DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy);
- (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
+ (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom /*, kbdHandle*/); // XKB disabled for now
}
/*
- * Class: jogamp_newt_driver_x11_X11Display
+ * Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DisplayRelease0
* Signature: (JJJ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DisplayRelease0
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_javaobject_atom = (Atom)javaObjectAtom;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -350,40 +337,54 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0
(void) wm_javaobject_atom;
(void) wm_delete_atom;
+ // XkbFreeKeyboard(kbdDesc, XkbAllNamesMask, True); // XKB disabled for now
+
XSync(dpy, True); // discard all pending events
DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy);
}
/*
- * Class: jogamp_newt_driver_x11_X11Display
+ * Class: jogamp_newt_driver_x11_DisplayDriver
* Method: DispatchMessages
- * Signature: (JIJJ)V
+ * Signature: (JJJ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
- (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0
+ (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/)
{
Display * dpy = (Display *) (intptr_t) display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ // XkbDescPtr kbdDesc = (XkbDescPtr)(intptr_t)kbdHandle; // XKB disabled for now
int num_events = 100;
+ int autoRepeatModifiers = 0;
if ( NULL == dpy ) {
return;
}
+ /** XKB disabled for now
+ if( NULL == kbdDesc) {
+ NewtCommon_throwNewRuntimeException(env, "NULL kbd handle, bail out!");
+ return;
+ } */
+
// Periodically take a break
while( num_events > 0 ) {
jobject jwindow = NULL;
XEvent evt;
KeySym keySym = 0;
+ KeyCode keyCode = 0;
+ jshort javaVKeyUS = 0;
+ jshort javaVKeyNN = 0;
jint modifiers = 0;
- char keyChar = 0;
+ uint16_t keyChar = 0;
+ jstring keyString = NULL;
char text[255];
// XEventsQueued(dpy, X):
- // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
// QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
// QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
- if ( 0 >= XPending(dpy) ) {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
// DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
return;
}
@@ -391,19 +392,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
XNextEvent(dpy, &evt);
num_events--;
- if( 0==evt.xany.window ) {
- NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
- return ;
- }
-
if(dpy!=evt.xany.display) {
NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
return ;
}
- // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
- NewtDisplay_displayDispatchErrorHandlerEnable(1, env);
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
#ifdef VERBOSE_ON
@@ -413,34 +412,91 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
#endif
);
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
-
if(NULL==jwindow) {
- fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
- (void*)dpy, evt.type, (void*)evt.xany.window);
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
continue;
}
switch(evt.type) {
case KeyRelease:
- case KeyPress:
- if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
- KeySym lower_return = 0, upper_return = 0;
- keyChar=text[0];
- XConvertCase(keySym, &lower_return, &upper_return);
- // always return upper case, set modifier masks (SHIFT, ..)
- keySym = X11KeySym2NewtVKey(upper_return);
+ if (XEventsQueued(dpy, QueuedAfterReading)) {
+ XEvent nevt;
+ XPeekEvent(dpy, &nevt);
+
+ if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time &&
+ nevt.xkey.keycode == evt.xkey.keycode)
+ {
+ autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK;
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
} else {
- keyChar=0;
- keySym = X11KeySym2NewtVKey(keySym);
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
+ // fall through intended
+ case KeyPress: {
+ KeySym shiftedKeySym; // layout depending keySym w/ SHIFT
+ KeySym unShiftedKeySym; // layout depending keySym w/o SHIFT
+ unsigned int xkey_state = evt.xkey.state;
+
+ keyCode = evt.xkey.keycode;
+
+ // Layout depending keySym w/o SHIFT,
+ // using fixed group 0 (US default layout)
+ //
+ // unsigned int mods_rtrn = 0;
+ // Bool res = XkbTranslateKeyCode (kbdDesc, keyCode, 0, &mods_rtrn, &keySym); // XKB disabled for now
+ // if( !res ) {
+ keySym = XkbKeycodeToKeysym(dpy, keyCode, 0 /* group */, 0 /* shift level */);
+ // }
+
+ text[0] = 0; text[1] = 0; text[2] = 0;
+ int charCount = XLookupString(&evt.xkey, text, 2, &shiftedKeySym, NULL);
+ if( 1 == charCount ) {
+ keyChar = 0x00FF & (uint16_t) (text[0]);
+ } else if( 2 == charCount ) {
+ // Example: UTF-16: 00DF, UTF-8: c3 9f, LATIN SMALL LETTER SHARP S
+ keyChar = ( 0x00FF & (uint16_t)(text[0]) ) << 8 | ( 0x00FF & (uint16_t)(text[1]) ); // UTF-16BE
+ keyString = (*env)->NewStringUTF(env, text);
+ }
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.0: keyCode 0x%X keySym 0x%X, (shifted: 0x%X)\n",
+ (int)keyCode, (int)keySym, (int) shiftedKeySym);
+ #endif
+ if( IS_WITHIN( shiftedKeySym, XK_KP_Space, XK_KP_9 ) ) {
+ // Use modded keySym for keypad for US and NN
+ keySym = shiftedKeySym;
+ unShiftedKeySym = shiftedKeySym;
+ } else if( 0 == keyChar ) {
+ // Use keyCode's keySym for dead-key (aka modifiers, etc)
+ unShiftedKeySym = keySym;
+ } else if( 0 == ( evt.xkey.state & ShiftCtrlModMask ) ) {
+ // Use non modded keySym
+ unShiftedKeySym = shiftedKeySym;
+ } else {
+ evt.xkey.state = evt.xkey.state & ~ShiftCtrlModMask; // clear shift, ctrl and Mod*
+ XLookupString(&evt.xkey, text, 0, &unShiftedKeySym, NULL);
+ // unShiftedKeySym = XLookupKeysym(&evt.xkey, 0 /* index ? */);
+ }
+
+ javaVKeyNN = X11KeySym2NewtVKey(unShiftedKeySym);
+ javaVKeyUS = X11KeySym2NewtVKey(keySym);
+ modifiers |= X11InputState2NewtModifiers(xkey_state, javaVKeyNN, evt.type == KeyPress) | autoRepeatModifiers;
+
+ #ifdef DEBUG_KEYS
+ fprintf(stderr, "NEWT X11 Key.X: keyCode 0x%X keySym 0x%X, (0x%X, shifted: 0x%X), keyChar '%c' 0x%X %d, javaVKey[US 0x%X, NN 0x%X], xstate 0x%X %u, jmods 0x%X\n",
+ (int)keyCode, (int)keySym, (int) unShiftedKeySym, (int)shiftedKeySym, keyChar, keyChar, charCount,
+ (int)javaVKeyUS, (int)javaVKeyNN,
+ (int)xkey_state, (int)xkey_state, (int)modifiers);
+ #endif
}
- modifiers = X11InputState2NewtModifiers(evt.xkey.state);
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
- modifiers = X11InputState2NewtModifiers(evt.xbutton.state);
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state, 0, JNI_FALSE);
break;
default:
@@ -450,87 +506,43 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
switch(evt.type) {
case ButtonPress:
(*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case ButtonRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
- modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED,
modifiers,
- (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/);
- #endif
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
break;
case MotionNotify:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
- modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED,
modifiers,
- (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/);
break;
case EnterNotify:
DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
break;
case LeaveNotify:
DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
- modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED,
modifiers,
- (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/);
- #endif
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/);
+ break;
+ case MappingNotify:
+ DBG_PRINT( "X11: event . MappingNotify call %p type %d\n", (void*)evt.xmapping.window, evt.xmapping.type);
+ XRefreshKeyboardMapping(&evt.xmapping);
break;
case KeyPress:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
- modifiers, keySym, (jchar) -1);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case KeyRelease:
- #ifdef USE_SENDIO_DIRECT
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #else
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
- modifiers, keySym, (jchar) -1);
-
- (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED,
- modifiers, keySym, (jchar) keyChar);
- #endif
-
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED,
+ modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
break;
case DestroyNotify:
DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
@@ -660,4 +672,59 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0
}
}
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: createPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ Cursor c;
+
+ if( 0 != pixels ) {
+ Display * dpy = (Display *) (intptr_t) display;
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ XcursorImage ci;
+ ci.version = 1; // XCURSOR_IMAGE_VERSION;
+ ci.size = width; // nominal size (assume square ..)
+ ci.width = width;
+ ci.height = height;
+ ci.xhot = hotX;
+ ci.yhot = hotY;
+ ci.delay = 0;
+ ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset);
+
+ c = XcursorImageLoadCursor (dpy, &ci);
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c);
+
+ } else {
+ c = 0;
+ }
+ return (jlong) (intptr_t) c;
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_DisplayDriver
+ * Method: destroyPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_destroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+
+ if( 0 != handle ) {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: destroyPointerIcon0: %p\n", (void *)c);
+ XFreeCursor(dpy, c);
+ }
+}
+
diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c
new file mode 100644
index 000000000..32a55c67c
--- /dev/null
+++ b/src/newt/native/X11Event.c
@@ -0,0 +1,305 @@
+
+#include "X11Event.h"
+
+void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong windowDeleteAtom) {
+ Atom wm_delete_atom = (Atom)windowDeleteAtom;
+ int num_events = 100;
+ int autoRepeatModifiers = 0;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ XEvent evt;
+ KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ char text[255];
+
+ // XEventsQueued(dpy, X):
+ // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?)
+ // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available
+ // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more ..
+ // if ( 0 >= XPending(dpy) )
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) )
+ {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+
+ XNextEvent(dpy, &evt);
+ num_events--;
+
+ if(dpy!=evt.xany.display) {
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }
+
+ if( 0==evt.xany.window ) {
+ DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type);
+ continue;
+ }
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
+
+ jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }
+
+ switch(evt.type) {
+ case KeyRelease:
+ if (XEventsQueued(dpy, QueuedAfterReading)) {
+ XEvent nevt;
+ XPeekEvent(dpy, &nevt);
+
+ if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time &&
+ nevt.xkey.keycode == evt.xkey.keycode)
+ {
+ autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK;
+ } else {
+ autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK;
+ }
+ }
+ // fall through intended
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = X11KeySym2NewtVKey(upper_return);
+ } else {
+ keyChar=0;
+ keySym = X11KeySym2NewtVKey(keySym);
+ }
+ modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers;
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ modifiers |= X11InputState2NewtModifiers(evt.xbutton.state);
+ break;
+
+ default:
+ break;
+ }
+
+ switch(evt.type) {
+ case ButtonPress:
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case ButtonRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
+ #endif
+ break;
+ case MotionNotify:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case EnterNotify:
+ DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case LeaveNotify:
+ DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED,
+ modifiers,
+ (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/);
+ #endif
+ break;
+ case KeyPress:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case KeyRelease:
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, keySym, (jchar) -1);
+ #endif
+
+ break;
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom
+ jboolean closed;
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+ break;
+
+ case Expose:
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
+
+ if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+ evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
+ }
+ break;
+
+ case MapNotify:
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect,
+ evt.xmap.event!=evt.xmap.window);
+ if( evt.xmap.event == evt.xmap.window ) {
+ // ignore child window notification
+ {
+ // update insets
+ int left, right, top, bottom;
+ NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+ }
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+ }
+ break;
+
+ case UnmapNotify:
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n",
+ (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure,
+ evt.xunmap.event!=evt.xunmap.window);
+ if( evt.xunmap.event == evt.xunmap.window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+ }
+ break;
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ evt.xreparent.x, evt.xreparent.y,
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+ (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+ }
+ break;
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window);
+ }
+ }
+}
diff --git a/src/newt/native/X11Event.h b/src/newt/native/X11Event.h
new file mode 100644
index 000000000..969bcdeed
--- /dev/null
+++ b/src/newt/native/X11Event.h
@@ -0,0 +1,9 @@
+
+#ifndef _X11Event_h
+#define _X11Event_h
+
+#include "X11Common.h"
+
+extern void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _X11Event_h */
diff --git a/src/newt/native/X11RandR11.c b/src/newt/native/X11RandR11.c
new file mode 100644
index 000000000..38d61289b
--- /dev/null
+++ b/src/newt/native/X11RandR11.c
@@ -0,0 +1,371 @@
+/**
+ * Copyright 2011 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.
+ */
+
+#include "X11Screen.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getAvailableScreenRotations0
+ * Signature: (JI)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getAvailableScreenRotations0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)scrn_idx);
+ int num_rotations = 0;
+ Rotation cur_rotation, rotations_supported;
+ int rotations[4];
+ int major, minor;
+
+ rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
+
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getNumScreenResolution0
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getNumScreenResolutions0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getNumScreenResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ DBG_PRINT("getNumScreenResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
+
+ return num_sizes;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenResolutions0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenResolution0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ // Fill the properties in temp jint array
+ int propIndex = 0;
+ jint prop[4];
+
+ prop[propIndex++] = xrrs[(int)resMode_idx].width;
+ prop[propIndex++] = xrrs[(int)resMode_idx].height;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
+ prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
+
+ jintArray properties = (*env)->NewIntArray(env, 4);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenRates0
+ * Signature: (JII)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenRates0
+ (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ int num_rates;
+ short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
+
+ jint prop[num_rates];
+ int i;
+ for(i=0; i<num_rates; i++) {
+ prop[i] = (int) rates[i];
+ /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
+ }
+
+ jintArray properties = (*env)->NewIntArray(env, num_rates);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getScreenConfiguration0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR11_getScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ // get current resolutions and frequencies
+ XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ return (jlong) (intptr_t) conf;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: freeScreenConfiguration0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR11_freeScreenConfiguration0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRate0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRate0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+ DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
+
+ return (jint) original_rate;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenRotation0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenRotation0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Rotation rotation;
+
+ XRRConfigCurrentConfiguration(conf, &rotation);
+
+ return NewtScreen_XRotation2Degree(env, rotation);
+}
+
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: getCurrentScreenResolutionIndex0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR11_getCurrentScreenResolutionIndex0
+ (JNIEnv *env, jclass clazz, jlong screenConfiguration)
+{
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+
+ short original_rate = XRRConfigCurrentRate(conf);
+
+ Rotation original_rotation;
+ SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
+
+ DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
+ return (jint)original_size_id;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModeStart0
+ * Signature: (JIJIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModeStart0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
+ resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
+
+ int xrot = NewtScreen_Degree2XRotation(env, rotation);
+
+ XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
+
+ XSync(dpy, False);
+ XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, xrot, (short)freq, CurrentTime);
+ XSync(dpy, False);
+
+ return JNI_TRUE;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR11
+ * Method: setCurrentScreenModePollEnd0
+ * Signature: (JIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR11_setCurrentScreenModePollEnd0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ int randr_event_base, randr_error_base;
+ XEvent evt;
+ XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
+
+ int num_sizes;
+ XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
+ XRRScreenConfiguration *conf;
+
+ if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
+ NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ }
+
+ XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
+
+ int done = 0;
+ int rot;
+ do {
+ if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
+ return JNI_FALSE; // not done
+ }
+ XNextEvent(dpy, &evt);
+
+ switch (evt.type - randr_event_base) {
+ case RRScreenChangeNotify:
+ if(0 < scn_event->rotation ) {
+ rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(1) %p (root %p) resIdx %d rot %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index, rot,
+ scn_event->width, scn_event->height);
+ // done = scn_event->size_index == resMode_idx; // not reliable ..
+ done = rot == rotation &&
+ scn_event->width == xrrs[resMode_idx].width &&
+ scn_event->height == xrrs[resMode_idx].height;
+ } else {
+ DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call(0) %p (root %p) resIdx %d %dx%d\n",
+ (void*)scn_event->window, (void*)scn_event->root,
+ (int)scn_event->size_index,
+ scn_event->width, scn_event->height);
+ }
+ break;
+ default:
+ DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
+ }
+ XRRUpdateConfiguration(&evt);
+ } while(!done);
+
+ XSync(dpy, False);
+
+ return done ? JNI_TRUE : JNI_FALSE;
+}
+
diff --git a/src/newt/native/X11RandR13.c b/src/newt/native/X11RandR13.c
new file mode 100644
index 000000000..92c20e893
--- /dev/null
+++ b/src/newt/native/X11RandR13.c
@@ -0,0 +1,515 @@
+/**
+ * Copyright 2011 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.
+ */
+
+#include "X11Common.h"
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getScreenResources0
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getScreenResources0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+
+ XRRScreenResources *res = XRRGetScreenResourcesCurrent( dpy, root); // 1.3
+ // XRRScreenResources *res = XRRGetScreenResources( dpy, root); // 1.2
+
+ return (jlong) (intptr_t) res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeScreenResources0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeScreenResources0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ if( NULL != resources ) {
+ XRRFreeScreenResources( resources );
+ }
+}
+
+#define SAFE_STRING(s) (NULL==s?"":s)
+
+static void dumpOutputs(const char *prefix, Display *dpy, XRRScreenResources *resources, int noutput, RROutput * outputs) {
+ int i, j;
+ fprintf(stderr, "%s %p: Output count %d\n", prefix, resources, noutput);
+ for(i=0; i<noutput; i++) {
+ RROutput output = outputs[i];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ fprintf(stderr, " Output[%d]: id %#lx, crtx 0x%X, name %s (%d), %lux%lu, ncrtc %d, .., nmode %d (preferred %d)\n",
+ i, output, xrrOutputInfo->crtc, SAFE_STRING(xrrOutputInfo->name), xrrOutputInfo->nameLen, xrrOutputInfo->mm_width, xrrOutputInfo->mm_height,
+ xrrOutputInfo->ncrtc, xrrOutputInfo->nmode, xrrOutputInfo->npreferred);
+ for(j=0; j<xrrOutputInfo->nmode; j++) {
+ fprintf(stderr, " Output[%d].Mode[%d].id %#lx\n", i, j, xrrOutputInfo->modes[j]);
+ }
+ XRRFreeOutputInfo (xrrOutputInfo);
+ }
+}
+
+/** Returns vertical refresh rate in hertz */
+static float getVRefresh(XRRModeInfo *mode) {
+ float rate;
+ unsigned int vTotal = mode->vTotal;
+
+ if (mode->modeFlags & RR_DoubleScan) {
+ /* doublescan doubles the number of lines */
+ vTotal *= 2;
+ }
+
+ if (mode->modeFlags & RR_Interlace) {
+ /* interlace splits the frame into two fields */
+ /* the field rate is what is typically reported by monitors */
+ vTotal /= 2;
+ }
+
+ if (mode->hTotal && vTotal) {
+ rate = ( (float) mode->dotClock /
+ ( (float) mode->hTotal * (float) vTotal )
+ );
+ } else {
+ rate = 0;
+ }
+ return rate;
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_dumpInfo0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ int pos[] = { 0, 0 } ;
+ int i, j, minWidth, minHeight, maxWidth, maxHeight;
+
+ int vs_width = DisplayWidth(dpy, screen_idx);
+ int vs_height = DisplayHeight(dpy, screen_idx);
+ int vs_width_mm = DisplayWidthMM(dpy, screen_idx);
+ int vs_height_mm = DisplayHeightMM(dpy, screen_idx);
+ fprintf(stderr, "ScreenVirtualSize: %dx%d %dx%d mm\n", vs_width, vs_height, vs_width_mm, vs_height_mm);
+
+ XRRGetScreenSizeRange (dpy, root, &minWidth, &minHeight, &maxWidth, &maxHeight);
+ fprintf(stderr, "XRRGetScreenSizeRange: %dx%d .. %dx%d\n", minWidth, minHeight, maxWidth, maxHeight);
+
+ if( NULL == resources ) {
+ fprintf(stderr, "XRRScreenResources NULL\n");
+ return;
+ }
+ fprintf(stderr, "XRRScreenResources %p: Crtc count %d\n", resources, resources->ncrtc);
+ for(i=0; i<resources->ncrtc; i++) {
+ RRCrtc crtc = resources->crtcs[i];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+ fprintf(stderr, "Crtc[%d]: %d/%d %dx%d, rot 0x%X, mode.id %#lx\n",
+ i, xrrCrtcInfo->x, xrrCrtcInfo->y, xrrCrtcInfo->width, xrrCrtcInfo->height, xrrCrtcInfo->rotations, xrrCrtcInfo->mode);
+ for(j=0; j<xrrCrtcInfo->noutput; j++) {
+ fprintf(stderr, " Crtc[%d].Output[%d].id %#lx\n", i, j, xrrCrtcInfo->outputs[j]);
+ }
+ XRRFreeCrtcInfo(xrrCrtcInfo);
+ }
+
+ dumpOutputs("XRRScreenResources.outputs", dpy, resources, resources->noutput, resources->outputs);
+
+ fprintf(stderr, "XRRScreenResources %p: Mode count %d\n", resources, resources->nmode);
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *mode = &resources->modes[i];
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ float refresh = getVRefresh(mode);
+ fprintf(stderr, "Mode[%d, id %#lx]: %ux%u@%f, name %s\n", i, mode->id, mode->width, mode->height, refresh, SAFE_STRING(mode->name));
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDeviceCount0
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDeviceCount0
+ (JNIEnv *env, jclass clazz, jlong screenResources)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ return ( NULL != resources ) ? resources->ncrtc : 0;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorInfoHandle0
+ * Signature: (JIJI)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint crt_idx)
+{
+ Display *dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || crt_idx >= resources->ncrtc ) {
+ return 0;
+ }
+ RRCrtc crtc = resources->crtcs[crt_idx];
+ XRRCrtcInfo *xrrCrtcInfo = XRRGetCrtcInfo (dpy, resources, crtc);
+
+ return (jlong) (intptr_t) xrrCrtcInfo;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: freeMonitorInfoHandle0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_RandR13_freeMonitorInfoHandle0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL != xrrCrtcInfo ) {
+ XRRFreeCrtcInfo( xrrCrtcInfo );
+ }
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getAvailableRotations0
+ * Signature: (J)I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getAvailableRotations0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ if( NULL == xrrCrtcInfo ) {
+ return NULL;
+ }
+ Rotation rotations_supported = xrrCrtcInfo->rotations;
+
+ int num_rotations = 0;
+ int rotations[4];
+ if(0 != (rotations_supported & RR_Rotate_0)) {
+ rotations[num_rotations++] = 0;
+ }
+ if(0 != (rotations_supported & RR_Rotate_90)) {
+ rotations[num_rotations++] = 90;
+ }
+ if(0 != (rotations_supported & RR_Rotate_180)) {
+ rotations[num_rotations++] = 180;
+ }
+ if(0 != (rotations_supported & RR_Rotate_270)) {
+ rotations[num_rotations++] = 270;
+ }
+
+ jintArray properties = NULL;
+
+ if(num_rotations>0) {
+ properties = (*env)->NewIntArray(env, num_rotations);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
+ }
+
+ // move from the temp structure to the java structure
+ (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
+ }
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorViewport0
+ * Signature: (J)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorViewport0
+ (JNIEnv *env, jclass clazz, jlong monitorInfo)
+{
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ jsize propCount = 4;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = xrrCrtcInfo->x;
+ prop[propIndex++] = xrrCrtcInfo->y;
+ prop[propIndex++] = xrrCrtcInfo->width;
+ prop[propIndex++] = xrrCrtcInfo->height;
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorMode0
+ * Signature: (JI)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jint mode_idx)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+
+ if( NULL == resources || mode_idx >= resources->nmode ) {
+ return NULL;
+ }
+
+ XRRModeInfo *mode = &resources->modes[mode_idx];
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = -1; // rotation placeholder
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorCurrentMode0
+ * Signature: (JJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorCurrentMode0
+ (JNIEnv *env, jclass clazz, jlong screenResources, jlong monitorInfo)
+{
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ int modeId = xrrCrtcInfo->mode;
+ XRRModeInfo *mode = NULL;
+ int i;
+ for(i=0; i<resources->nmode; i++) {
+ XRRModeInfo *imode = &resources->modes[i];
+ if( imode->id == modeId ) {
+ mode = imode;
+ break;
+ }
+ }
+ if( NULL == mode ) {
+ // oops ..
+ return NULL;
+ }
+
+ unsigned int dots = mode->hTotal * mode->vTotal;
+ int refresh = (int) ( getVRefresh(mode) * 100.0f ); // Hz * 100
+ int flags = 0;
+ if (mode->modeFlags & RR_Interlace) {
+ flags |= FLAG_INTERLACE;
+ }
+ if (mode->modeFlags & RR_DoubleScan) {
+ flags |= FLAG_DOUBLESCAN;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mode->width;
+ prop[propIndex++] = mode->height;
+ prop[propIndex++] = 32; // TODO: XRandR > 1.4 may support bpp
+ prop[propIndex++] = refresh;
+ prop[propIndex++] = flags;
+ prop[propIndex++] = mode->id;
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: getMonitorDevice0
+ * Signature: (JJJJ)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_RandR13_getMonitorDevice0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return NULL;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return NULL;
+ }
+
+ RROutput output = xrrCrtcInfo->outputs[0];
+ XRROutputInfo * xrrOutputInfo = XRRGetOutputInfo (dpy, resources, output);
+ int numModes = xrrOutputInfo->nmode;
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 + numModes;
+ jint prop[ propCount ];
+ int propIndex = 0;
+
+ prop[propIndex++] = propCount;
+ prop[propIndex++] = crt_idx;
+ prop[propIndex++] = xrrOutputInfo->mm_width;
+ prop[propIndex++] = xrrOutputInfo->mm_height;
+ prop[propIndex++] = xrrCrtcInfo->x;
+ prop[propIndex++] = xrrCrtcInfo->y;
+ prop[propIndex++] = xrrCrtcInfo->width;
+ prop[propIndex++] = xrrCrtcInfo->height;
+ prop[propIndex++] = xrrCrtcInfo->mode; // current mode id
+ prop[propIndex++] = NewtScreen_XRotation2Degree(env, xrrCrtcInfo->rotation);
+ int i;
+ for(i=0; i<numModes; i++) {
+ // avail modes ..
+ prop[propIndex++] = xrrOutputInfo->modes[i];
+ }
+
+ XRRFreeOutputInfo (xrrOutputInfo);
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setMonitorMode0
+ * Signature: (JJJIIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setMonitorMode0
+ (JNIEnv *env, jclass clazz, jlong display, jlong screenResources, jlong monitorInfo, jint crt_idx, jint modeId, jint rotation, jint x, jint y)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ XRRCrtcInfo *xrrCrtcInfo = (XRRCrtcInfo *) (intptr_t) monitorInfo;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources || NULL == xrrCrtcInfo || crt_idx >= resources->ncrtc ) {
+ // n/a
+ return res;
+ }
+
+ if( None == xrrCrtcInfo->mode || 0 == xrrCrtcInfo->noutput ) {
+ // disabled
+ return res;
+ }
+
+ if( 0 >= modeId ) {
+ // oops ..
+ return res;
+ }
+
+ if( 0 > x || 0 > y ) {
+ x = xrrCrtcInfo->x;
+ y = xrrCrtcInfo->y;
+ }
+
+ Status status = XRRSetCrtcConfig( dpy, resources, resources->crtcs[crt_idx], CurrentTime,
+ x, y, modeId, NewtScreen_Degree2XRotation(env, rotation),
+ xrrCrtcInfo->outputs, xrrCrtcInfo->noutput );
+ res = status == RRSetConfigSuccess;
+
+ return res;
+}
+
+/*
+ * Class: jogamp_newt_driver_x11_RandR13
+ * Method: setScreenViewport0
+ * Signature: (JIJIIII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_RandR13_setScreenViewport0
+ (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenResources, jint x, jint y, jint width, jint height)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window root = RootWindow(dpy, (int)screen_idx);
+ XRRScreenResources *resources = (XRRScreenResources *) (intptr_t) screenResources;
+ jboolean res = JNI_FALSE;
+
+ if( NULL == resources ) {
+ // n/a
+ return JNI_FALSE;
+ }
+
+ XRRSetScreenSize (dpy, root, width, height, DisplayWidthMM(dpy, screen_idx), DisplayHeightMM(dpy, screen_idx));
+ return JNI_TRUE;
+}
+
+
diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c
index 698eed89d..152a092c9 100644
--- a/src/newt/native/X11Screen.c
+++ b/src/newt/native/X11Screen.c
@@ -29,18 +29,18 @@
// #define VERBOSE_ON 1
// #define DBG_PERF 1
-#include "X11Common.h"
+#include "X11Screen.h"
#ifdef DBG_PERF
#include "timespec.h"
#endif
/*
- * Class: jogamp_newt_driver_x11_X11Screen
+ * Class: jogamp_newt_driver_x11_ScreenDriver
* Method: GetScreen
* Signature: (JI)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_GetScreen0
(JNIEnv *env, jclass clazz, jlong display, jint screen_index)
{
Display * dpy = (Display *)(intptr_t)display;
@@ -60,432 +60,80 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0
return (jlong) (intptr_t) scrn;
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getWidth0
(JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
{
Display * dpy = (Display *) (intptr_t) display;
return (jint) DisplayWidth( dpy, scrn_idx);
}
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getHeight0
(JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
{
Display * dpy = (Display *) (intptr_t) display;
return (jint) DisplayHeight( dpy, scrn_idx);
}
-static int showedRandRVersion = 0;
-
-static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) {
- if( 0 == XRRQueryVersion(dpy, major, minor) ) {
- return False;
- }
- if(0 == showedRandRVersion) {
- DBG_PRINT("X11 RandR Version %d.%d\n", *major, *minor);
- showedRandRVersion = 1;
- }
- return True;
-}
-
-static Bool NewtScreen_hasRANDR(Display *dpy) {
- int major, minor;
- return NewtScreen_getRANDRVersion(dpy, &major, &minor);
-}
-
-static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
- int rot;
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) {
+ int degree;
if(xrotation == RR_Rotate_0) {
- rot = 0;
+ degree = 0;
}
else if(xrotation == RR_Rotate_90) {
- rot = 90;
+ degree = 90;
}
else if(xrotation == RR_Rotate_180) {
- rot = 180;
+ degree = 180;
}
else if(xrotation == RR_Rotate_270) {
- rot = 270;
+ degree = 270;
} else {
NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation);
}
- return rot;
+ return degree;
}
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getAvailableScreenModeRotations0
- * Signature: (JI)I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)scrn_idx);
- int num_rotations = 0;
- Rotation cur_rotation, rotations_supported;
- int rotations[4];
- int major, minor;
-
- if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) {
- fprintf(stderr, "RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation);
-
- if(0 != (rotations_supported & RR_Rotate_0)) {
- rotations[num_rotations++] = 0;
- }
- if(0 != (rotations_supported & RR_Rotate_90)) {
- rotations[num_rotations++] = 90;
- }
- if(0 != (rotations_supported & RR_Rotate_180)) {
- rotations[num_rotations++] = 180;
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree) {
+ int xrot;
+ if(degree == 0) {
+ xrot = RR_Rotate_0;
}
- if(0 != (rotations_supported & RR_Rotate_270)) {
- rotations[num_rotations++] = 270;
- }
-
- jintArray properties = NULL;
-
- if(num_rotations>0) {
- properties = (*env)->NewIntArray(env, num_rotations);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations);
- }
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations);
- }
-
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getNumScreenModeResolution0
- * Signature: (JI)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n");
- return 0;
- }
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getNumScreenModeResolution0.2 (XRRSizes): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- DBG_PRINT("getNumScreenModeResolutions0: %p:%d -> %d\n", dpy, (int)scrn_idx, num_sizes);
-
- return num_sizes;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getScreenModeResolutions0
- * Signature: (JII)[I
- */
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
+ else if(degree == 90) {
+ xrot = RR_Rotate_90;
}
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
+ else if(degree == 180) {
+ xrot = RR_Rotate_180;
}
-
- // Fill the properties in temp jint array
- int propIndex = 0;
- jint prop[4];
-
- prop[propIndex++] = xrrs[(int)resMode_idx].width;
- prop[propIndex++] = xrrs[(int)resMode_idx].height;
- prop[propIndex++] = xrrs[(int)resMode_idx].mwidth;
- prop[propIndex++] = xrrs[(int)resMode_idx].mheight;
-
- jintArray properties = (*env)->NewIntArray(env, 4);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4);
+ else if(degree == 270) {
+ xrot = RR_Rotate_270;
+ } else {
+ NewtCommon_throwNewRuntimeException(env, "invalid degree: %d", degree);
}
-
- // move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, 4, prop);
-
- return properties;
+ return xrot;
}
/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getScreenModeRates0
- * Signature: (JII)[I
+ * Class: jogamp_newt_driver_x11_ScreenDriver
+ * Method: GetRandRVersion0
+ * Signature: (J)[I
*/
-JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0
- (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx)
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_ScreenDriver_getRandRVersion0
+ (JNIEnv *env, jclass clazz, jlong display)
{
- Display *dpy = (Display *) (intptr_t) display;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n");
- return (*env)->NewIntArray(env, 0);
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- int num_rates;
- short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates);
-
- jint prop[num_rates];
- int i;
- for(i=0; i<num_rates; i++) {
- prop[i] = (int) rates[i];
- /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */
+ Display * dpy = (Display *)(intptr_t)display;
+ jint version[2];
+ if( 0 == XRRQueryVersion(dpy, &version[0], &version[1] ) ) {
+ version[0] = 0;
+ version[1] = 0;
}
-
- jintArray properties = (*env)->NewIntArray(env, num_rates);
- if (properties == NULL) {
- NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates);
+ jintArray jversion = (*env)->NewIntArray(env, 2);
+ if (jversion == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
}
// move from the temp structure to the java structure
- (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop);
+ (*env)->SetIntArrayRegion(env, jversion, 0, 2, version);
- return properties;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getScreenConfiguration0
- * Signature: (JI)J
- */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx)
-{
- Display *dpy = (Display *) (intptr_t) display;
- Window root = RootWindow(dpy, (int)screen_idx);
-#ifdef DBG_PERF
- struct timespec t0, t1, td;
- long td_ms;
- timespec_now(&t0);
-#endif
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenConfiguration0: RANDR not available\n");
- return 0;
- }
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.1: %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- // get current resolutions and frequencies
- XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root);
-#ifdef DBG_PERF
- timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
- fprintf(stderr, "X11Screen_getScreenConfiguration0.2 (XRRGetScreenInfo): %ld ms\n", td_ms); fflush(NULL);
-#endif
-
- return (jlong) (intptr_t) conf;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: freeScreenConfiguration0
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Screen_freeScreenConfiguration0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRFreeScreenConfigInfo( (XRRScreenConfiguration *) (intptr_t) screenConfiguration );
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getCurrentScreenRate0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
- DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate);
-
- return (jint) original_rate;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getCurrentScreenRotation0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Rotation rotation;
-
- XRRConfigCurrentConfiguration(conf, &rotation);
-
- return NewtScreen_XRotation2Degree(env, rotation);
-}
-
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: getCurrentScreenResolutionIndex0
- * Signature: (J)I
- */
-JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0
- (JNIEnv *env, jclass clazz, jlong screenConfiguration)
-{
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
-
- short original_rate = XRRConfigCurrentRate(conf);
-
- Rotation original_rotation;
- SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);
-
- DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id);
- return (jint)original_size_id;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: setCurrentScreenModeStart0
- * Signature: (JIJIII)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jlong screenConfiguration, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- XRRScreenConfiguration *conf = (XRRScreenConfiguration *) (intptr_t) screenConfiguration;
- Window root = RootWindow(dpy, (int)screen_idx);
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- int rot;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- switch(rotation) {
- case 0:
- rot = RR_Rotate_0;
- break;
- case 90:
- rot = RR_Rotate_90;
- break;
- case 180:
- rot = RR_Rotate_180;
- break;
- case 270:
- rot = RR_Rotate_270;
- break;
- default:
- NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation);
- }
-
- DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n",
- resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation);
-
- XRRSelectInput (dpy, root, RRScreenChangeNotifyMask);
-
- XSync(dpy, False);
- XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime);
- XSync(dpy, False);
-
- return JNI_TRUE;
-}
-
-/*
- * Class: jogamp_newt_driver_x11_X11Screen
- * Method: setCurrentScreenModePollEnd0
- * Signature: (J)Z
- */
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0
- (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation)
-{
- Display *dpy = (Display *) (intptr_t) display;
- int randr_event_base, randr_error_base;
- XEvent evt;
- XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt;
-
- if(False == NewtScreen_hasRANDR(dpy)) {
- DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n");
- return JNI_FALSE;
- }
-
- int num_sizes;
- XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions
- XRRScreenConfiguration *conf;
-
- if( 0 > resMode_idx || resMode_idx >= num_sizes ) {
- NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes);
- }
-
- XRRQueryExtension(dpy, &randr_event_base, &randr_error_base);
-
- int done = 0;
- int rot;
- do {
- if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) {
- return;
- }
- XNextEvent(dpy, &evt);
-
- switch (evt.type - randr_event_base) {
- case RRScreenChangeNotify:
- rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation);
- DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n",
- (void*)scn_event->window, (void*)scn_event->root,
- (int)scn_event->size_index, rot,
- scn_event->width, scn_event->height);
- // done = scn_event->size_index == resMode_idx; // not reliable ..
- done = rot == rotation &&
- scn_event->width == xrrs[resMode_idx].width &&
- scn_event->height == xrrs[resMode_idx].height;
- break;
- default:
- DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window);
- }
- XRRUpdateConfiguration(&evt);
- } while(!done);
-
- XSync(dpy, False);
-
+ return jversion;
}
diff --git a/src/newt/native/X11Screen.h b/src/newt/native/X11Screen.h
new file mode 100644
index 000000000..c81ee05d5
--- /dev/null
+++ b/src/newt/native/X11Screen.h
@@ -0,0 +1,38 @@
+/**
+ * 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.
+ */
+
+#ifndef _X11SCREEN_H
+#define _X11SCREEN_H
+
+
+#include "X11Common.h"
+
+int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation);
+int NewtScreen_Degree2XRotation(JNIEnv *env, int degree);
+
+#endif /* _X11SCREEN_H */
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 0f93b3e76..2cc66c78d 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -98,11 +98,11 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon
}
jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
unsigned char * jogl_java_object_data_pp = NULL;
- jobject jwindow;
+ jobject jwindow = 0;
{
unsigned long nitems= 0;
@@ -122,7 +122,9 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja
}
if(actual_type!=(Atom)javaObjectAtom || nitems<nitems_32 || NULL==jogl_java_object_data_pp) {
- XFree(jogl_java_object_data_pp);
+ if( NULL != jogl_java_object_data_pp ) {
+ XFree(jogl_java_object_data_pp);
+ }
if(True==showWarning) {
fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom NEWT_JAVA_OBJECT window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, NEWT_JAVA_OBJECT %ld, result 0!\n",
res, nitems, bytes_after, (long)actual_type, (long)javaObjectAtom);
@@ -189,8 +191,8 @@ static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window
return 0; // Error
}
static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left, int *right, int *top, int *bottom) {
- Atom actual_type;
- int actual_format;
+ Atom actual_type = 0;
+ int actual_format = 0;
int nitems_32 = 4; // l, r, t, b
unsigned char * frame_extends_data_pp = NULL;
@@ -210,7 +212,9 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left
}
if(nitems<nitems_32 || NULL==frame_extends_data_pp) {
- XFree(frame_extends_data_pp);
+ if( NULL != frame_extends_data_pp ) {
+ XFree(frame_extends_data_pp);
+ }
// DBG_PRINT( "Warning: NEWT X11Window: Fetched invalid Atom _NET_FRAME_EXTENTS window property (res %d) nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, _NET_FRAME_EXTENTS %ld, result 0!\n",
// res, nitems, bytes_after, (long)actual_type, actual_format, _NET_FRAME_EXTENTS);
return 0; // Error, but ok - ie window not mapped
@@ -271,18 +275,21 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
#ifdef DECOR_USE_MWM
Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
- unsigned char *wm_data;
- Atom wm_type;
- int wm_format;
- unsigned long wm_nitems, wm_bytes_after;
+ unsigned char *wm_data = NULL;
+ Atom wm_type = 0;
+ int wm_format = 0;
+ unsigned long wm_nitems = 0, wm_bytes_after = 0;
if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType,
&wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) {
- if(wm_type != None) {
+ if(wm_type != None && NULL != wm_data && wm_nitems >= PROP_MWM_HINTS_ELEMENTS) {
// unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
unsigned long *hints = (unsigned long *) wm_data;
decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] );
}
+ if( NULL != wm_data ) {
+ XFree(wm_data);
+ }
}
#endif
@@ -299,9 +306,8 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
-
-#define _NET_WM_FULLSCREEN ( 1 << 0 )
-#define _NET_WM_ABOVE ( 1 << 1 )
+#define _NET_WM_STATE_FLAG_FULLSCREEN ( 1 << 0 )
+#define _NET_WM_STATE_FLAG_ABOVE ( 1 << 1 )
/**
* Set fullscreen using Extended Window Manager Hints (EWMH)
@@ -314,101 +320,98 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
* and resets it when leaving FS.
* The same is assumed for the decoration state.
*/
-static int NewtWindows_isFullscreenEWMHSupported (Display *dpy, Window w) {
+static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
+#ifdef VERBOSE_ON
+ // Code doesn't work reliable on KDE4 ...
Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
- Atom * actions;
- Atom type;
- unsigned long action_len, remain;
- int res = 0, form, i;
+ Atom * actions = NULL;
+ Atom type = 0;
+ unsigned long action_len = 0, remain = 0;
+ int res = 0, form = 0, i = 0;
Status s;
if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
&type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
- for(i=0; i<action_len; i++) {
- if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
- res |= _NET_WM_FULLSCREEN ;
- } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
- res |= _NET_WM_ABOVE ;
- }
-#ifdef VERBOSE_ON
- else {
- char * astr = XGetAtomName(dpy, actions[i]);
- DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
- XFree(astr);
+ if( NULL != actions ) {
+ for(i=0; i<action_len; i++) {
+ if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_FULLSCREEN ;
+ } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
+ res |= _NET_WM_STATE_FLAG_ABOVE ;
+ }
+ else {
+ char * astr = XGetAtomName(dpy, actions[i]);
+ DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
+ XFree(astr);
+ }
}
-#endif
+ XFree(actions);
}
DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res);
} else {
DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
}
- // above code doesn't work reliable on KDE4 ...
- res = _NET_WM_FULLSCREEN | _NET_WM_ABOVE ;
- return res;
+#endif
+ return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ;
}
-static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
+static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
- int ewmhMask = NewtWindows_isFullscreenEWMHSupported(dpy, w);
+ int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w);
+ Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ;
+ Bool changeAbove = 0 != ( ( _NET_WM_STATE_FLAG_ABOVE & ewmhMask ) & ewmhFlags ) ;
Bool res = False;
if(0 == ewmhMask) {
return res;
}
- if(!isVisible && True==enable) {
- Atom types[2]={0};
- int ntypes=0;
-
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- types[ntypes++] = _NET_WM_STATE_ABOVE;
- }
- if(ntypes>0) {
- XChangeProperty( dpy, w, _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
- XSync(dpy, False);
- res = True;
- }
- } else {
- if(enable) {
- NewtWindows_setCWAbove(dpy, w);
- }
- XEvent xev;
- long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
- int i=0;
-
- memset ( &xev, 0, sizeof(xev) );
-
- xev.type = ClientMessage;
- xev.xclient.window = w;
- xev.xclient.message_type = _NET_WM_STATE;
- xev.xclient.format = 32;
+ // _NET_WM_STATE: fullscreen and/or above
+ if( changeFullscreen || changeAbove ) {
+ {
+ // _NET_WM_STATE as event to root window
+ XEvent xev;
+ long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
+ int i=0;
- xev.xclient.data.l[i++] = ( True == enable ) ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
- if( 0 != ( ( _NET_WM_FULLSCREEN & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
- }
- if( 0 != ( ( _NET_WM_ABOVE & ewmhMask ) & ewmhFlags ) ) {
- xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
- }
- xev.xclient.data.l[3] = 1; //source indication for normal applications
+ memset ( &xev, 0, sizeof(xev) );
+
+ xev.type = ClientMessage;
+ xev.xclient.window = w;
+ xev.xclient.message_type = _NET_WM_STATE;
+ xev.xclient.format = 32;
+
+ xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+ if( changeFullscreen ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
+ }
+ if( changeAbove ) {
+ xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
+ }
+ xev.xclient.data.l[3] = 1; //source indication for normal applications
- if(i>0) {
XSendEvent ( dpy, root, False, mask, &xev );
- res = True;
}
+ // Also change _NET_WM_BYPASS_COMPOSITOR!
+ // A value of 0 indicates no preference.
+ // A value of 1 hints the compositor to disabling compositing of this window.
+ // A value of 2 hints the compositor to not disabling compositing of this window
+ {
+ Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False );
+ unsigned long value = enable ? 1 : 0;
+ XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
+ }
+ XSync(dpy, False);
+ res = True;
}
- XSync(dpy, False);
- DBG_PRINT( "X11: reconfigureWindow0 FULLSCREEN EWMH ON %d, ewmhMask 0x%X, ewmhFlags 0x%X, visible %d: %d\n",
- enable, ewmhMask, ewmhFlags, isVisible, res);
+ DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n",
+ enable, changeFullscreen, changeAbove, isVisible, res);
return res;
}
@@ -438,7 +441,7 @@ Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Wind
return 0; // Error
}
-static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
+static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) {
XWindowAttributes xwa;
Window focus_return;
int revert_to_return;
@@ -447,7 +450,7 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
XGetInputFocus(dpy, &focus_return, &revert_to_return);
DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w);
- if( JNI_TRUE==force || focus_return!=w) {
+ if( True==force || focus_return!=w) {
DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w);
XRaiseWindow(dpy, w);
NewtWindows_setCWAbove(dpy, w);
@@ -467,11 +470,11 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy,
*/
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: initIDs
* Signature: ()Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_initIDs0
(JNIEnv *env, jclass clazz)
{
return JNI_TRUE;
@@ -504,15 +507,22 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint
}
}
+static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) {
+ Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False);
+ Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False);
+ XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size);
+}
+
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: CreateWindow
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
(JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index,
jint visualID,
jlong javaObjectAtom, jlong windowDeleteAtom,
- jint x, jint y, jint width, jint height, jboolean autoPosition, int flags)
+ jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
+ jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -632,12 +642,27 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
{
XEvent event;
int left=0, right=0, top=0, bottom=0;
+ 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);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
XSync(dpy, False);
+ if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// send insets before visibility, allowing java code a proper sync point!
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
(*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
@@ -657,7 +682,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
NewtWindows_setPosSize(dpy, window, x, y, width, height);
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- NewtWindows_setFullscreenEWMH(dpy, root, window, _NET_WM_ABOVE, True, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True);
}
}
@@ -666,16 +691,17 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
}
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: CloseWindow
* Signature: (JJ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0
- (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom)
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
+ (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/) // XKB disabled for now
{
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
jobject jwindow;
+ XWindowAttributes xwa;
if(dpy==NULL) {
NewtCommon_FatalError(env, "invalid display connection..");
@@ -694,42 +720,47 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_CloseWindow0
}
XSync(dpy, False);
+ memset(&xwa, 0, sizeof(XWindowAttributes));
+ XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
XSelectInput(dpy, w, 0);
XUnmapWindow(dpy, w);
- XSync(dpy, False);
// Drain all events related to this window ..
- Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom);
+ Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
XDestroyWindow(dpy, w);
- XSync(dpy, False);
+ if( None != xwa.colormap ) {
+ XFreeColormap(dpy, xwa.colormap);
+ }
+ XSync(dpy, True); // discard all events now, no more handler
(*env)->DeleteGlobalRef(env, jwindow);
DBG_PRINT( "X11: CloseWindow END\n");
}
-#if 0
+// #define REPARENT_WAIT_FOR_REPARENT_NOTIFY 1
+
+#ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
- return (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ Bool res = (event->type == ReparentNotify) && (event->xreparent.window == (Window) arg);
+ #ifdef VERBOSE_ON
+ if( event->type == ReparentNotify ) {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event ReparentNotify: Result %d, exp %p, has %p\n", (int)res, arg, event->xreparent.window);
+ } else {
+ DBG_PRINT( "X11.WaitForReparentNotify: Event 0x%X: Result %d, exp %p, has %p\n", (int)event->type, (int)res, arg, event->xreparent.window);
+ }
+ #endif
+ return res;
}
#endif
-/**
- * KDE cause lost input focus in fullscreen mode.
- * Using 'XGrabKeyboard(..)' would prevent the loss,
- * but also would disable WM task switcher etc.
- *
- * #define FS_GRAB_KEYBOARD 1
- *
- */
-
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: reconfigureWindow0
* Signature: (JIJJIIIII)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0
(JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index,
jlong jparent, jlong jwindow, jlong windowDeleteAtom,
jint x, jint y, jint width, jint height, jint flags)
@@ -742,51 +773,60 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
XEvent event;
Bool isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
Bool tempInvisible = ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_PARENTING(flags) ) && isVisible ;
+ // Bool tempInvisible = TST_FLAG_CHANGE_PARENTING(flags) && isVisible ;
int fsEWMHFlags = 0;
if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
- fsEWMHFlags |= _NET_WM_FULLSCREEN;
+ if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) { // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;
+ }
if( TST_FLAG_IS_FULLSCREEN(flags) ) {
if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs on, above on
- } // else { } // fs on, above off
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on, above on
+ } // else { } // fs on, above off
} else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // fs off, above off
- } // else { } // fs off, above on
- }
- if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
- fsEWMHFlags |= _NET_WM_ABOVE; // toggle above
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs off, above off
+ } // else { } // fs off, above on
+ } else if( TST_FLAG_CHANGE_PARENTING(flags) ) {
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN; // fs off
+ if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // above off
+ }
+ } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
+ fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // toggle above
}
- NewtDisplay_displayDispatchErrorHandlerEnable(1, env);
-
- DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
+ DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
(void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
x, y, width, height,
TST_FLAG_CHANGE_PARENTING(flags), TST_FLAG_HAS_PARENT(flags),
TST_FLAG_CHANGE_DECORATION(flags), TST_FLAG_IS_UNDECORATED(flags),
- TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags),
+ TST_FLAG_CHANGE_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags),
TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
- TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags), tempInvisible, fsEWMHFlags);
+ TST_FLAG_CHANGE_VISIBILITY(flags), TST_FLAG_IS_VISIBLE(flags),
+ tempInvisible, fsEWMHFlags);
- // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state shall be enough.
+ // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough.
// However, we have to consider other cases like reparenting and WM which don't support it.
-
+ #if 0 // Also doesn't work work properly w/ Unity WM
if( fsEWMHFlags && !TST_FLAG_CHANGE_PARENTING(flags) && isVisible &&
+ !TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
- if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
- if(TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- } else {
- XUngrabKeyboard(dpy, CurrentTime);
- }
- } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) {
- XUngrabKeyboard(dpy, CurrentTime);
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
+ if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
+ NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
}
- #endif
+ DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n");
+ return;
+ }
+ }
+ #endif
+ // Toggle ALWAYSONTOP (only) w/o visibility or window stacking sideffects
+ if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONTOP(flags) &&
+ !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
+ if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, TST_FLAG_IS_ALWAYSONTOP(flags)) ) {
+ DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n");
return;
}
}
@@ -798,21 +838,22 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
// no need to notify the java side .. just temp change
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False);
- #ifdef FS_GRAB_KEYBOARD
- XUngrabKeyboard(dpy, CurrentTime);
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) || // FS off
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop off
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
// TOP: in -> out
DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom
+ // Fix for Unity WM, i.e. _remove_ persistent previous states
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
}
if( TST_FLAG_CHANGE_DECORATION(flags) ) {
@@ -827,7 +868,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
// CHILD: out -> in
DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n");
XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
- // XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
+ XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+ #endif
XSync(dpy, False);
}
@@ -836,62 +879,58 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
XMapRaised(dpy, w);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w );
// no need to notify the java side .. just temp change
- }
-
- if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
+ } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
if( TST_FLAG_IS_VISIBLE(flags) ) {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
XMapRaised(dpy, w);
+ XSync(dpy, False);
+ // WM may disregard pos/size XConfigureWindow requests for invisible windows!
+ DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
+ NewtWindows_setPosSize(dpy, w, x, y, width, height);
} else {
DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n");
XUnmapWindow(dpy, w);
+ XSync(dpy, False);
}
- XSync(dpy, False);
}
- if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) ||
- ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on
- NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True);
- #ifdef FS_GRAB_KEYBOARD
- if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) {
- XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
- }
- #endif
+ if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) || // FS on
+ ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop on
+ NewtWindows_requestFocus (dpy, w, True);
+ NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True);
}
- NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
-
- DBG_PRINT( "X11: reconfigureWindow0 X\n");
+ DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
}
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: requestFocus0
* Signature: (JJZ)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_requestFocus0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
(JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
{
- NewtWindows_requestFocus ( env, obj, (Display *) (intptr_t) display, (Window)window, force ) ;
+ NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ;
}
/*
- * Class: jogamp_newt_driver_x11_X11Window
+ * Class: jogamp_newt_driver_x11_WindowDriver
* Method: getParentWindow0
* Signature: (JJ)J
*/
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_getParentWindow0
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow0
(JNIEnv *env, jclass clazz, jlong display, jlong window)
{
return (jlong) NewtWindows_getParent ((Display *) (intptr_t) display, (Window)window);
}
/*
- * Class: Java_jogamp_newt_driver_x11_X11Window
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: setTitle0
* Signature: (JJLjava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
(JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title)
{
Display * dpy = (Display *) (intptr_t) display;
@@ -938,11 +977,32 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_setTitle0
}
/*
- * Class: Java_jogamp_newt_driver_x11_X11Window
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
+ * Method: setPointerIcon0
+ * Signature: (JJILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle)
+{
+ Display * dpy = (Display *) (intptr_t) display;
+ Window w = (Window)window;
+
+ if( 0 == handle ) {
+ DBG_PRINT( "X11: setPointerIcon0: reset\n");
+ XUndefineCursor(dpy, w);
+ } else {
+ Cursor c = (Cursor) (intptr_t) handle;
+ DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c);
+ XDefineCursor(dpy, w, c);
+ }
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: setPointerVisible0
* Signature: (JJZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisible0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVisible0
(JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean mouseVisible)
{
static char noData[] = { 0,0,0,0,0,0,0,0 };
@@ -972,11 +1032,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_setPointerVisib
}
/*
- * Class: Java_jogamp_newt_driver_x11_X11Window
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: confinePointer0
* Signature: (JJZ)Z
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePointer0
(JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean confine)
{
Display * dpy = (Display *) (intptr_t) display;
@@ -995,11 +1055,11 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0
}
/*
- * Class: Java_jogamp_newt_driver_x11_X11Window
+ * Class: Java_jogamp_newt_driver_x11_WindowDriver
* Method: warpPointer0
* Signature: (JJII)V
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_warpPointer0
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_warpPointer0
(JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y)
{
Display * dpy = (Display *) (intptr_t) display;
diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c
new file mode 100644
index 000000000..d02d5a4ba
--- /dev/null
+++ b/src/newt/native/XCBEvent.c
@@ -0,0 +1,308 @@
+
+#define VERBOSE_ON 1
+
+#include "XCBEvent.h"
+
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/Xlib-xcb.h>
+
+void XCBSetEventQueueOwner(Display *dpy) {
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+}
+
+void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom) {
+ int num_events = 100;
+ xcb_connection_t *conn = NULL;
+
+ if ( NULL == dpy ) {
+ return;
+ }
+ conn = XGetXCBConnection(dpy);
+
+ // Periodically take a break
+ while( num_events > 0 ) {
+ jobject jwindow = NULL;
+ xcb_generic_event_t *evt;
+ // KeySym keySym = 0;
+ jint modifiers = 0;
+ char keyChar = 0;
+ // char text[255];
+
+ evt = xcb_poll_for_event(conn);
+ if(NULL == evt) {
+ // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy);
+ return;
+ }
+ num_events--;
+
+ /*if( 0==evt.xany.window ) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!");
+ return ;
+ }
+
+ if(dpy!=evt.xany.display) {
+ free(evt);
+ NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!");
+ return ;
+ }*/
+
+ // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type);
+
+ // X11WindowDisplayErrorHandlerEnable(1, env);
+
+ // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
+
+ //X11WindowDisplayErrorHandlerEnable(0, env);
+
+ /*if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)dpy, evt.type, (void*)evt.xany.window);
+ continue;
+ }*/
+
+ uint8_t xcb_event_type = evt->response_type & ~0x80;
+ xcb_window_t event_window = 0;
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS:
+ case XCB_BUTTON_RELEASE:
+ event_window = ((xcb_button_press_event_t *)evt)->event;
+ modifiers = X11InputState2NewtModifiers(((xcb_button_press_event_t *)evt)->state);
+ break;
+ case XCB_MOTION_NOTIFY:
+ event_window = ((xcb_motion_notify_event_t *)evt)->event;
+ break;
+ case XCB_KEY_PRESS:
+ case XCB_KEY_RELEASE: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ event_window = _evt->event;
+ /*
+ xcb_keycode_t detail = _evt->detail;
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ KeySym lower_return = 0, upper_return = 0;
+ keyChar=text[0];
+ XConvertCase(keySym, &lower_return, &upper_return);
+ // always return upper case, set modifier masks (SHIFT, ..)
+ keySym = upper_return;
+ modifiers = X11InputState2NewtModifiers(evt.xkey.state);
+ } else {
+ keyChar=0;
+ }*/
+ }
+ break;
+ case XCB_EXPOSE:
+ event_window = ((xcb_expose_event_t *)evt)->window;
+ break;
+ case XCB_MAP_NOTIFY:
+ event_window = ((xcb_map_notify_event_t *)evt)->window;
+ break;
+ case XCB_UNMAP_NOTIFY:
+ event_window = ((xcb_unmap_notify_event_t *)evt)->window;
+ break;
+ }
+ if(0==event_window) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d, no X11 window associated\n",
+ (void*)dpy, xcb_event_type);
+ continue;
+ }
+ jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
+ #ifdef VERBOSE_ON
+ True
+ #else
+ False
+ #endif
+ );
+ if(NULL==jwindow) {
+ fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n",
+ (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window);
+ continue;
+ }
+
+ switch( xcb_event_type ) {
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt;
+ (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED,
+ modifiers,
+ (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
+ #endif
+ } break;
+ case XCB_KEY_PRESS: {
+ xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+ } break;
+ case XCB_KEY_RELEASE: {
+ xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt;
+ event_window = ((xcb_key_release_event_t *)evt)->event;
+ #ifdef USE_SENDIO_DIRECT
+ (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #else
+ (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED,
+ modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
+ #endif
+
+ } break;
+ /*
+ case DestroyNotify:
+ DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n",
+ (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event);
+ if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) {
+ // ignore child destroy notification
+ }
+ break;
+ case CreateNotify:
+ DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n",
+ (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent);
+ break;
+ case ConfigureNotify:
+ DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n",
+ (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above,
+ evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height,
+ evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
+ if ( evt.xconfigure.window == evt.xconfigure.event ) {
+ // ignore child window change notification
+ (*env)->CallVoidMethod(env, jwindow, sizeChangedID,
+ (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
+ (*env)->CallVoidMethod(env, jwindow, positionChangedID,
+ (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
+ }
+ break;
+ case ClientMessage:
+ if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
+ DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n",
+ (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
+ (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+ // Called by Window.java: CloseWindow();
+ num_events = 0; // end loop in case of destroyed display
+ }
+ break;
+
+ case FocusIn:
+ DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE);
+ break;
+
+ case FocusOut:
+ DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
+ (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+ break;
+ */
+
+ case XCB_EXPOSE: {
+ xcb_expose_event_t *_evt = (xcb_expose_event_t *)evt;
+ DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)(intptr_t)_evt->window,
+ _evt->x, _evt->y, _evt->width, _evt->height, _evt->count);
+
+ if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) {
+ (*env)->CallVoidMethod(env, jwindow, windowRepaintID,
+ _evt->x, _evt->y, _evt->width, _evt->height);
+ }
+ } break;
+
+ case XCB_MAP_NOTIFY: {
+ xcb_map_notify_event_t *_evt = (xcb_map_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window, (int)_evt->override_redirect,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+ }
+ } break;
+
+ case XCB_UNMAP_NOTIFY: {
+ xcb_unmap_notify_event_t *_evt = (xcb_unmap_notify_event_t *)evt;
+ DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, child-event: %d\n",
+ (void*)(intptr_t)_evt->event, (void*)(intptr_t)_evt->window,
+ _evt->event!=_evt->window);
+ if( _evt->event == _evt->window ) {
+ // ignore child window notification
+ (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+ }
+ } break;
+ /*
+
+ case ReparentNotify:
+ {
+ jlong parentResult; // 0 if root, otherwise proper value
+ Window winRoot, winTopParent;
+ #ifdef VERBOSE_ON
+ Window oldParentRoot, oldParentTopParent;
+ Window parentRoot, parentTopParent;
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) {
+ oldParentRoot=0; oldParentTopParent = 0;
+ }
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) {
+ parentRoot=0; parentTopParent = 0;
+ }
+ #endif
+ if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) {
+ winRoot=0; winTopParent = 0;
+ }
+ if(evt.xreparent.parent == winRoot) {
+ parentResult = 0; // our java indicator for root window
+ } else {
+ parentResult = (jlong) (intptr_t) evt.xreparent.parent;
+ }
+ #ifdef VERBOSE_ON
+ DBG_PRINT( "X11: event . ReparentNotify: call OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n",
+ (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent,
+ (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
+ (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
+ #endif
+
+ (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult);
+ }
+ break;
+ */
+
+ // unhandled events .. yet ..
+
+ default:
+ DBG_PRINT("XCB: event . unhandled %d 0x%X call %p\n", (int)xcb_event_type, (unsigned int)xcb_event_type, (void*)(intptr_t)event_window);
+ }
+ free(evt);
+ }
+}
+
+
diff --git a/src/newt/native/XCBEvent.h b/src/newt/native/XCBEvent.h
new file mode 100644
index 000000000..d70797566
--- /dev/null
+++ b/src/newt/native/XCBEvent.h
@@ -0,0 +1,10 @@
+
+#ifndef _XCBEvent_h
+#define _XCBEvent_h
+
+#include "X11Common.h"
+
+extern void XCBSetEventQueueOwner(Display *dpy);
+extern void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong wmDeleteAtom);
+
+#endif /* _XCBDisplayXCBEvent_h */
diff --git a/src/newt/native/BroadcomEGL.c b/src/newt/native/bcm_egl.c
index df6aca611..9b960d278 100644
--- a/src/newt/native/BroadcomEGL.c
+++ b/src/newt/native/bcm_egl.c
@@ -37,7 +37,7 @@
#include <stdio.h>
#include <string.h>
-#include "jogamp_newt_driver_broadcom_egl_Window.h"
+#include "jogamp_newt_driver_bcm_egl_WindowDriver.h"
#include "MouseEvent.h"
#include "KeyEvent.h"
@@ -67,7 +67,7 @@ static jmethodID windowCreatedID = NULL;
* Display
*/
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_DispatchMessages
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_DispatchMessages
(JNIEnv *env, jobject obj)
{
// FIXME: n/a
@@ -75,7 +75,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_DispatchMess
(void) obj;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_CreateDisplay
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_CreateDisplay
(JNIEnv *env, jobject obj, jint width, jint height)
{
(void) env;
@@ -89,7 +89,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_CreateDispl
return (jlong) (intptr_t) dpy;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_DestroyDisplay
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_DisplayDriver_DestroyDisplay
(JNIEnv *env, jobject obj, jlong display)
{
EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
@@ -106,7 +106,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Display_DestroyDispl
* Window
*/
-JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_initIDs
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_initIDs
(JNIEnv *env, jclass clazz)
{
windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(III)V");
@@ -118,7 +118,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_initIDs
return JNI_TRUE;
}
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_CreateWindow
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_CreateWindow
(JNIEnv *env, jobject obj, jlong display, jboolean chromaKey, jint width, jint height)
{
EGLDisplay dpy = (EGLDisplay)(intptr_t)display;
@@ -162,7 +162,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_CreateWindow
return (jlong) (intptr_t) window;
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_CloseWindow
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_CloseWindow
(JNIEnv *env, jobject obj, jlong display, jlong window)
{
EGLDisplay dpy = (EGLDisplay) (intptr_t) display;
@@ -175,7 +175,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_CloseWindow
DBG_PRINT( "[CloseWindow] X\n");
}
-JNIEXPORT void JNICALL Java_jogamp_newt_driver_broadcom_egl_Window_SwapWindow
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_egl_WindowDriver_SwapWindow
(JNIEnv *env, jobject obj, jlong display, jlong window)
{
EGLDisplay dpy = (EGLDisplay) (intptr_t) display;
diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c
new file mode 100644
index 000000000..ee59f0aa6
--- /dev/null
+++ b/src/newt/native/bcm_vc_iv.c
@@ -0,0 +1,463 @@
+/**
+ * Copyright 2012 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * See references in header file.
+ */
+#include "bcm_vc_iv.h"
+
+#include "jogamp_newt_driver_bcm_vc_iv_DisplayDriver.h"
+#include "jogamp_newt_driver_bcm_vc_iv_ScreenDriver.h"
+#include "jogamp_newt_driver_bcm_vc_iv_WindowDriver.h"
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+typedef struct {
+ DISPMANX_ELEMENT_HANDLE_T handle; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int width; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int height; // magic BCM EGL position (EGL_DISPMANX_WINDOW_T)
+ int x;
+ int y;
+ int32_t layer;
+} BCM_ELEMENT_T;
+
+typedef struct {
+ DISPMANX_RESOURCE_HANDLE_T handle;
+ VC_IMAGE_TYPE_T type;
+ uint32_t native_image_handle;
+} BCM_RESOURCE_T;
+
+typedef struct {
+ BCM_ELEMENT_T element;
+ BCM_RESOURCE_T resource;
+ int hotX, hotY;
+} POINTER_ICON_T;
+
+static jmethodID setScreenSizeID = NULL;
+
+static jmethodID sizeChangedID = NULL;
+static jmethodID positionChangedID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+
+/**
+ * Display
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ bcm_host_init();
+ // TODO: bcm_host_deinit();
+ DBG_PRINT( "BCM.Display initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_OpenBCMDisplay0
+ (JNIEnv *env, jclass clazz)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
+ DBG_PRINT( "BCM.Display Open %p\n", (void*)(intptr_t)dispman_display);
+ return (jlong) (intptr_t) dispman_display;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CloseBCMDisplay0
+ (JNIEnv *env, jclass clazz, jlong display)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ DBG_PRINT( "BCM.Display Close %p\n", (void*)(intptr_t)dispman_display);
+ vc_dispmanx_display_close( dispman_display );
+}
+
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DispatchMessages0
+ (JNIEnv *env, jclass clazz)
+{
+}
+
+static void bcm_moveTo(DISPMANX_ELEMENT_HANDLE_T element, uint32_t layer, int x, int y, int width, int height) {
+ VC_RECT_T src_rect;
+ VC_RECT_T dst_rect;
+ uint32_t change_flags = DISPMANX_ELEMENT_CHANGE_DEST_RECT | DISPMANX_ELEMENT_CHANGE_SRC_RECT;
+ DISPMANX_RESOURCE_HANDLE_T mask = 0;
+ DISPMANX_TRANSFORM_T transform = 0;
+
+ uint8_t opacity = 0; // NOP
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = width << 16;
+ src_rect.height = height << 16;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_change_attributes( dispman_update,
+ element,
+ change_flags,
+ layer,
+ opacity,
+ &dst_rect,
+ &src_rect,
+ mask,
+ transform );
+ vc_dispmanx_update_submit_sync( dispman_update );
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_CreatePointerIcon0
+ (JNIEnv *env, jclass clazz, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
+{
+ if( 0 == pixels ) {
+ return 0;
+ }
+ int32_t success = 0;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+ int x = 0;
+ int y = 0;
+ int pitch = width * 4; // RGBA
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+
+ POINTER_ICON_T * p = calloc(1, sizeof(POINTER_ICON_T));
+ p->hotX = hotX;
+ p->hotY = hotY;
+ p->element.layer = 2000;
+ p->element.x = x;
+ p->element.y = y;
+ p->element.width = width;
+ p->element.height = height;
+ p->resource.type = VC_IMAGE_ARGB8888; /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ p->resource.handle = vc_dispmanx_resource_create( p->resource.type,
+ width,
+ height,
+ &(p->resource.native_image_handle) );
+
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ vc_dispmanx_resource_write_data( p->resource.handle,
+ p->resource.type,
+ pitch,
+ (void*)(intptr_t)(pixelPtr + pixels_byte_offset),
+ &dst_rect );
+
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Create PI %p, resource %p\n", p, (void*)(intptr_t)p->resource.handle);
+ return (jlong) (intptr_t) p;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_DestroyPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ if( 0 == p ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Destroy.0 PI %p, resource %p, element %p\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle);
+
+ if( 0 != p->element.handle ) {
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ if( 0 != p->resource.handle ) {
+ vc_dispmanx_resource_delete( p->resource.handle );
+ p->resource.handle = 0;
+ }
+ free( p );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_SetPointerIcon0
+ (JNIEnv *env, jclass clazz, jlong display, jlong handle, jboolean enable, jint x, jint y)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ if( 0 == dispman_display || NULL == p || 0 == p->resource.handle ) {
+ return;
+ }
+
+ DBG_PRINT( "BCM.Display PointerIcon.Set.0 %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+
+ if( enable ) {
+ if( 0 != p->element.handle ) {
+ return;
+ }
+
+ p->element.x = x;
+ p->element.y = y;
+ dst_rect.x = p->element.x - p->hotX;
+ dst_rect.y = p->element.y - p->hotY;
+ dst_rect.width = p->element.width;
+ dst_rect.height = p->element.height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = p->element.width << 16;
+ src_rect.height = p->element.height << 16;
+
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ p->element.handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->element.layer, &dst_rect,
+ p->resource.handle /*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
+ vc_dispmanx_update_submit_sync( dispman_update );
+ } else {
+ // DISABLE
+ if( 0 == p->element.handle ) {
+ return;
+ }
+ p->element.x = x;
+ p->element.y = y;
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->element.handle );
+ p->element.handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Set.X %p, PI %p, resource %p, element %p - enable %d - %d/%d\n",
+ (void*)(intptr_t)display, p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, enable, x, y);
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_DisplayDriver_MovePointerIcon0
+ (JNIEnv *env, jclass clazz, jlong handle, jint x, jint y)
+{
+ POINTER_ICON_T * p = (POINTER_ICON_T *) (intptr_t) handle ;
+
+ if( NULL == p || 0 == p->element.handle ) {
+ return;
+ }
+ DBG_PRINT( "BCM.Display PointerIcon.Move.0 PI %p, resource %p, element %p - %d/%d\n",
+ p, (void*)(intptr_t)p->resource.handle, (void*)(intptr_t)p->element.handle, x, y);
+ p->element.x = x;
+ p->element.y = y;
+ bcm_moveTo( p->element.handle, p->element.layer, p->element.x - p->hotX, p->element.y - p->hotY, p->element.width, p->element.height);
+}
+
+/**
+ * Screen
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ uint32_t screen_width;
+ uint32_t screen_height;
+ int32_t success = 0;
+
+ setScreenSizeID = (*env)->GetMethodID(env, clazz, "setScreenSize", "(II)V");
+ if (setScreenSizeID == NULL) {
+ DBG_PRINT( "BCM.Screen initIDs FALSE\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT( "BCM.Screen initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_ScreenDriver_initNative
+ (JNIEnv *env, jobject obj)
+{
+ uint32_t screen_width;
+ uint32_t screen_height;
+ int32_t success = 0;
+
+ if( graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height) >= 0 ) {
+ DBG_PRINT( "BCM.Screen initNative ok %dx%d\n", screen_width, screen_height );
+ (*env)->CallVoidMethod(env, obj, setScreenSizeID, (jint) screen_width, (jint) screen_height);
+ } else {
+ DBG_PRINT( "BCM.Screen initNative failed\n" );
+ }
+}
+
+/**
+ * Window
+ */
+
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
+ if (sizeChangedID == NULL ||
+ positionChangedID == NULL ||
+ visibleChangedID == NULL ||
+ windowDestroyNotifyID == NULL) {
+ DBG_PRINT( "initIDs failed\n" );
+ return JNI_FALSE;
+ }
+ DBG_PRINT( "BCM.Window initIDs ok\n" );
+ return JNI_TRUE;
+}
+
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWindow0
+ (JNIEnv *env, jobject obj, jlong display, jint layer, jint x, jint y, jint width, jint height, jboolean opaque, jint alphaBits)
+{
+ int32_t success = 0;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ if( 0 == display ) {
+ return;
+ }
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = width;
+ dst_rect.height = height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = width << 16;
+ src_rect.height = height << 16;
+
+ VC_DISPMANX_ALPHA_T dispman_alpha;
+ memset(&dispman_alpha, 0x0, sizeof(VC_DISPMANX_ALPHA_T));
+
+ if( JNI_TRUE == opaque ) {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0;
+ } else {
+ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE ;
+ dispman_alpha.opacity = 0xFF;
+ dispman_alpha.mask = 0xFF;
+ }
+
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+
+ DBG_PRINT( "BCM.Display Window.Create.0 %p, %d/%d %dx%d, opaque %d, alphaBits %d, layer %d\n",
+ (void*)(intptr_t)dispman_display, x, y, width, height, opaque, alphaBits, layer);
+
+ BCM_ELEMENT_T * p = calloc(1, sizeof(BCM_ELEMENT_T));
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ p->layer = layer;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+ p->handle = vc_dispmanx_element_add ( dispman_update, dispman_display,
+ p->layer, &dst_rect, 0/*src*/,
+ &src_rect, DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha */, 0/*clamp*/, 0/*transform*/);
+
+ vc_dispmanx_update_submit_sync( dispman_update );
+
+ (*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_FALSE, JNI_TRUE); // FIXME: or defer=true ?
+
+ DBG_PRINT( "BCM.Display Window.Create.X %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
+
+ return (jlong) (intptr_t) p;
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CloseWindow0
+ (JNIEnv *env, jobject obj, jlong display, jlong window)
+{
+ DISPMANX_DISPLAY_HANDLE_T dispman_display = (DISPMANX_DISPLAY_HANDLE_T) (intptr_t) display;
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
+
+ DBG_PRINT( "BCM.Display Window.Close %p, element %p\n",
+ (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle);
+
+ if( 0 == dispman_display || NULL == p || 0 == p->handle ) {
+ return;
+ }
+ DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start( 0 );
+ vc_dispmanx_element_remove( dispman_update, p->handle );
+ p->handle = 0;
+ vc_dispmanx_update_submit_sync( dispman_update );
+ free( p );
+}
+
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_reconfigure0
+ (JNIEnv *env, jobject obj, jlong window, jint x, jint y, jint width, jint height, jint flags)
+{
+ BCM_ELEMENT_T * p = (BCM_ELEMENT_T *) (intptr_t) window ;
+
+ if( NULL == p || 0 == p->handle ) {
+ return;
+ }
+ /***
+ int isVisible = !TST_FLAG_CHANGE_VISIBILITY(flags) && TST_FLAG_IS_VISIBLE(flags) ;
+ ...
+ see X11Window.c
+ */
+
+ int posChanged = p->x != x || p->y != y;
+ int sizeChanged = p->width != width || p->height != height;
+ p->x = x;
+ p->y = y;
+ p->width = width;
+ p->height = height;
+
+ DBG_PRINT( "BCM.Display Window.Reconfig %p, element %p - %d/%d %dx%d\n",
+ p, (void*)(intptr_t)p->handle, p->x, p->y, p->width, p->height);
+
+ bcm_moveTo( p->handle, p->layer, p->x, p->y, p->width, p->height);
+ if( posChanged ) {
+ (*env)->CallVoidMethod(env, obj, positionChangedID, JNI_FALSE, x, y);
+ }
+ if( sizeChanged ) {
+ (*env)->CallVoidMethod(env, obj, sizeChangedID, JNI_FALSE, (jint) width, (jint) height, JNI_FALSE);
+ }
+}
+
diff --git a/src/newt/native/bcm_vc_iv.h b/src/newt/native/bcm_vc_iv.h
new file mode 100644
index 000000000..42189f3d6
--- /dev/null
+++ b/src/newt/native/bcm_vc_iv.h
@@ -0,0 +1,305 @@
+/**
+ * Copyright 2012 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.
+ */
+
+#ifndef BCM_VC_IV_H
+#define BCM_VC_IV_H
+
+/**
+ * http://en.wikipedia.org/wiki/VideoCore
+ * https://github.com/raspberrypi/userland
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef uint32_t DISPMANX_PROTECTION_T;
+typedef uint32_t DISPMANX_RESOURCE_HANDLE_T;
+typedef uint32_t DISPMANX_DISPLAY_HANDLE_T;
+typedef uint32_t DISPMANX_UPDATE_HANDLE_T;
+typedef uint32_t DISPMANX_ELEMENT_HANDLE_T;
+
+#define DISPMANX_NO_HANDLE 0
+
+#define DISPMANX_PROTECTION_MAX 0x0f
+#define DISPMANX_PROTECTION_NONE 0
+#define DISPMANX_PROTECTION_HDCP 11 // Derived from the WM DRM levels, 101-300
+
+
+
+/* Default display IDs.
+ Note: if you overwrite with you own dispmanx_platfrom_init function, you
+ should use IDs you provided during dispmanx_display_attach.
+*/
+#define DISPMANX_ID_MAIN_LCD 0
+#define DISPMANX_ID_AUX_LCD 1
+#define DISPMANX_ID_HDMI 2
+#define DISPMANX_ID_SDTV 3
+
+/* Return codes. Nonzero ones indicate failure. */
+typedef enum {
+ DISPMANX_SUCCESS = 0,
+ DISPMANX_INVALID = -1
+ /* XXX others TBA */
+} DISPMANX_STATUS_T;
+
+typedef enum {
+ /* Bottom 2 bits sets the orientation */
+ DISPMANX_NO_ROTATE = 0,
+ DISPMANX_ROTATE_90 = 1,
+ DISPMANX_ROTATE_180 = 2,
+ DISPMANX_ROTATE_270 = 3,
+
+ DISPMANX_FLIP_HRIZ = 1 << 16,
+ DISPMANX_FLIP_VERT = 1 << 17
+} DISPMANX_TRANSFORM_T;
+
+typedef enum {
+ /* Bottom 2 bits sets the alpha mode */
+ DISPMANX_FLAGS_ALPHA_FROM_SOURCE = 0,
+ DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS = 1,
+ DISPMANX_FLAGS_ALPHA_FIXED_NON_ZERO = 2,
+ DISPMANX_FLAGS_ALPHA_FIXED_EXCEED_0X07 = 3,
+
+ DISPMANX_FLAGS_ALPHA_PREMULT = 1 << 16,
+ DISPMANX_FLAGS_ALPHA_MIX = 1 << 17
+} DISPMANX_FLAGS_ALPHA_T;
+
+struct VC_IMAGE_T;
+typedef struct VC_IMAGE_T VC_IMAGE_T;
+
+typedef struct {
+ DISPMANX_FLAGS_ALPHA_T flags;
+ uint32_t opacity;
+ VC_IMAGE_T *mask;
+} DISPMANX_ALPHA_T;
+
+typedef struct {
+ DISPMANX_FLAGS_ALPHA_T flags;
+ uint32_t opacity;
+ DISPMANX_RESOURCE_HANDLE_T mask;
+} VC_DISPMANX_ALPHA_T; /* for use with vmcs_host */
+
+
+typedef enum {
+ DISPMANX_FLAGS_CLAMP_NONE = 0,
+ DISPMANX_FLAGS_CLAMP_LUMA_TRANSPARENT = 1,
+#if __VCCOREVER__ >= 0x04000000
+ DISPMANX_FLAGS_CLAMP_TRANSPARENT = 2,
+ DISPMANX_FLAGS_CLAMP_REPLACE = 3
+#else
+ DISPMANX_FLAGS_CLAMP_CHROMA_TRANSPARENT = 2,
+ DISPMANX_FLAGS_CLAMP_TRANSPARENT = 3
+#endif
+} DISPMANX_FLAGS_CLAMP_T;
+
+typedef enum {
+ DISPMANX_FLAGS_KEYMASK_OVERRIDE = 1,
+ DISPMANX_FLAGS_KEYMASK_SMOOTH = 1 << 1,
+ DISPMANX_FLAGS_KEYMASK_CR_INV = 1 << 2,
+ DISPMANX_FLAGS_KEYMASK_CB_INV = 1 << 3,
+ DISPMANX_FLAGS_KEYMASK_YY_INV = 1 << 4
+} DISPMANX_FLAGS_KEYMASK_T;
+
+typedef union {
+ struct {
+ uint8_t yy_upper;
+ uint8_t yy_lower;
+ uint8_t cr_upper;
+ uint8_t cr_lower;
+ uint8_t cb_upper;
+ uint8_t cb_lower;
+ } yuv;
+ struct {
+ uint8_t red_upper;
+ uint8_t red_lower;
+ uint8_t blue_upper;
+ uint8_t blue_lower;
+ uint8_t green_upper;
+ uint8_t green_lower;
+ } rgb;
+} DISPMANX_CLAMP_KEYS_T;
+
+typedef struct {
+ DISPMANX_FLAGS_CLAMP_T mode;
+ DISPMANX_FLAGS_KEYMASK_T key_mask;
+ DISPMANX_CLAMP_KEYS_T key_value;
+ uint32_t replace_value;
+} DISPMANX_CLAMP_T;
+
+
+typedef struct tag_VC_RECT_T {
+ int32_t x;
+ int32_t y;
+ int32_t width;
+ int32_t height;
+} VC_RECT_T;
+
+/* Types of image supported. */
+/* Please add any new types to the *end* of this list. Also update
+ * case_VC_IMAGE_ANY_xxx macros (below), and the vc_image_type_info table in
+ * vc_image/vc_image_helper.c.
+ */
+typedef enum
+{
+ VC_IMAGE_MIN = 0, //bounds for error checking
+
+ VC_IMAGE_RGB565 = 1,
+ VC_IMAGE_1BPP,
+ VC_IMAGE_YUV420,
+ VC_IMAGE_48BPP,
+ VC_IMAGE_RGB888,
+ VC_IMAGE_8BPP,
+ VC_IMAGE_4BPP, // 4bpp palettised image
+ VC_IMAGE_3D32, /* A separated format of 16 colour/light shorts followed by 16 z values */
+ VC_IMAGE_3D32B, /* 16 colours followed by 16 z values */
+ VC_IMAGE_3D32MAT, /* A separated format of 16 material/colour/light shorts followed by 16 z values */
+ VC_IMAGE_RGB2X9, /* 32 bit format containing 18 bits of 6.6.6 RGB, 9 bits per short */
+ VC_IMAGE_RGB666, /* 32-bit format holding 18 bits of 6.6.6 RGB */
+ VC_IMAGE_PAL4_OBSOLETE, // 4bpp palettised image with embedded palette
+ VC_IMAGE_PAL8_OBSOLETE, // 8bpp palettised image with embedded palette
+ VC_IMAGE_RGBA32, /* RGB888 with an alpha byte after each pixel */ /* xxx: isn't it BEFORE each pixel? */
+ VC_IMAGE_YUV422, /* a line of Y (32-byte padded), a line of U (16-byte padded), and a line of V (16-byte padded) */
+ VC_IMAGE_RGBA565, /* RGB565 with a transparent patch */
+ VC_IMAGE_RGBA16, /* Compressed (4444) version of RGBA32 */
+ VC_IMAGE_YUV_UV, /* VCIII codec format */
+ VC_IMAGE_TF_RGBA32, /* VCIII T-format RGBA8888 */
+ VC_IMAGE_TF_RGBX32, /* VCIII T-format RGBx8888 */
+ VC_IMAGE_TF_FLOAT, /* VCIII T-format float */
+ VC_IMAGE_TF_RGBA16, /* VCIII T-format RGBA4444 */
+ VC_IMAGE_TF_RGBA5551, /* VCIII T-format RGB5551 */
+ VC_IMAGE_TF_RGB565, /* VCIII T-format RGB565 */
+ VC_IMAGE_TF_YA88, /* VCIII T-format 8-bit luma and 8-bit alpha */
+ VC_IMAGE_TF_BYTE, /* VCIII T-format 8 bit generic sample */
+ VC_IMAGE_TF_PAL8, /* VCIII T-format 8-bit palette */
+ VC_IMAGE_TF_PAL4, /* VCIII T-format 4-bit palette */
+ VC_IMAGE_TF_ETC1, /* VCIII T-format Ericsson Texture Compressed */
+ VC_IMAGE_BGR888, /* RGB888 with R & B swapped */
+ VC_IMAGE_BGR888_NP, /* RGB888 with R & B swapped, but with no pitch, i.e. no padding after each row of pixels */
+ VC_IMAGE_BAYER, /* Bayer image, extra defines which variant is being used */
+ VC_IMAGE_CODEC, /* General wrapper for codec images e.g. JPEG from camera */
+ VC_IMAGE_YUV_UV32, /* VCIII codec format */
+ VC_IMAGE_TF_Y8, /* VCIII T-format 8-bit luma */
+ VC_IMAGE_TF_A8, /* VCIII T-format 8-bit alpha */
+ VC_IMAGE_TF_SHORT,/* VCIII T-format 16-bit generic sample */
+ VC_IMAGE_TF_1BPP, /* VCIII T-format 1bpp black/white */
+ VC_IMAGE_OPENGL,
+ VC_IMAGE_YUV444I, /* VCIII-B0 HVS YUV 4:4:4 interleaved samples */
+ VC_IMAGE_YUV422PLANAR, /* Y, U, & V planes separately (VC_IMAGE_YUV422 has them interleaved on a per line basis) */
+ VC_IMAGE_ARGB8888, /* 32bpp with 8bit alpha at MS byte, with R, G, B (LS byte) */
+ VC_IMAGE_XRGB8888, /* 32bpp with 8bit unused at MS byte, with R, G, B (LS byte) */
+
+ VC_IMAGE_YUV422YUYV, /* interleaved 8 bit samples of Y, U, Y, V */
+ VC_IMAGE_YUV422YVYU, /* interleaved 8 bit samples of Y, V, Y, U */
+ VC_IMAGE_YUV422UYVY, /* interleaved 8 bit samples of U, Y, V, Y */
+ VC_IMAGE_YUV422VYUY, /* interleaved 8 bit samples of V, Y, U, Y */
+
+ VC_IMAGE_RGBX32, /* 32bpp like RGBA32 but with unused alpha */
+ VC_IMAGE_RGBX8888, /* 32bpp, corresponding to RGBA with unused alpha */
+ VC_IMAGE_BGRX8888, /* 32bpp, corresponding to BGRA with unused alpha */
+
+ VC_IMAGE_YUV420SP, /* Y as a plane, then UV byte interleaved in plane with with same pitch, half height */
+
+ VC_IMAGE_YUV444PLANAR, /* Y, U, & V planes separately 4:4:4 */
+
+ VC_IMAGE_MAX, //bounds for error checking
+ VC_IMAGE_FORCE_ENUM_16BIT = 0xffff,
+} VC_IMAGE_TYPE_T;
+
+/**
+ * From https://github.com/raspberrypi/userland/blob/master/interface/vmcs_host/vc_vchi_dispmanx.h
+ */
+typedef enum {
+ DISPMANX_ELEMENT_CHANGE_LAYER = (1<<0),
+ DISPMANX_ELEMENT_CHANGE_OPACITY = (1<<1),
+ DISPMANX_ELEMENT_CHANGE_DEST_RECT = (1<<2),
+ DISPMANX_ELEMENT_CHANGE_SRC_RECT = (1<<3),
+ DISPMANX_ELEMENT_CHANGE_MASK_RESOURCE = (1<<4),
+ DISPMANX_ELEMENT_CHANGE_TRANSFORM = (1<<5)
+/**
+ * Not working /validated !
+ DISPMANX_ELEMENT_CHANGE_MIN = 0x00,
+ DISPMANX_ELEMENT_CHANGE_SOURCE = 0x01,
+ DISPMANX_ELEMENT_INSERT_ABOVE = 0x80,
+ DISPMANX_ELEMENT_CHANGE_FLAGS = 0x100,
+ DISPMANX_ELEMENT_CHANGE_NOTHING = 0x200,
+ DISPMANX_ELEMENT_CHANGE_ALPHA_FLAGS = 0x400,
+ DISPMANX_ELEMENT_CHANGE_PROTECTION = 0x800,
+ DISPMANX_ELEMENT_CHANGE_MAX = 0x1000
+ */
+} DISPMANX_ELEMENT_CHANGE_T;
+
+
+
+extern void bcm_host_init(void);
+extern void bcm_host_deinit(void);
+
+extern int32_t graphics_get_display_size( const uint16_t display_number,
+ uint32_t *width,
+ uint32_t *height);
+
+extern DISPMANX_DISPLAY_HANDLE_T vc_dispmanx_display_open( uint32_t device );
+extern int vc_dispmanx_display_close( DISPMANX_DISPLAY_HANDLE_T display );
+
+extern DISPMANX_RESOURCE_HANDLE_T vc_dispmanx_resource_create(VC_IMAGE_TYPE_T type, uint32_t width, uint32_t height, uint32_t *native_image_handle);
+extern int vc_dispmanx_resource_write_data( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch, void * src_address, const VC_RECT_T * rect );
+//extern int vc_dispmanx_resource_write_data_handle( DISPMANX_RESOURCE_HANDLE_T res, VC_IMAGE_TYPE_T src_type, int src_pitch,
+// VCHI_MEM_HANDLE_T handle, uint32_t offset, const VC_RECT_T * rect );
+extern int vc_dispmanx_resource_delete( DISPMANX_RESOURCE_HANDLE_T res );
+
+
+
+extern DISPMANX_UPDATE_HANDLE_T vc_dispmanx_update_start( int32_t priority );
+extern DISPMANX_ELEMENT_HANDLE_T vc_dispmanx_element_add ( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_DISPLAY_HANDLE_T display,
+ int32_t layer, const VC_RECT_T *dest_rect, DISPMANX_RESOURCE_HANDLE_T src,
+ const VC_RECT_T *src_rect, DISPMANX_PROTECTION_T protection,
+ VC_DISPMANX_ALPHA_T *alpha,
+ DISPMANX_CLAMP_T *clamp, DISPMANX_TRANSFORM_T transform );
+extern int vc_dispmanx_element_remove( DISPMANX_UPDATE_HANDLE_T update, DISPMANX_ELEMENT_HANDLE_T element );
+
+
+extern int vc_dispmanx_update_submit_sync( DISPMANX_UPDATE_HANDLE_T update );
+
+//New function added to VCHI to change attributes, set_opacity does not work there.
+extern int vc_dispmanx_element_change_attributes( DISPMANX_UPDATE_HANDLE_T update,
+ DISPMANX_ELEMENT_HANDLE_T element,
+ uint32_t change_flags,
+ int32_t layer,
+ uint8_t opacity,
+ const VC_RECT_T *dest_rect,
+ const VC_RECT_T *src_rect,
+ DISPMANX_RESOURCE_HANDLE_T mask,
+ DISPMANX_TRANSFORM_T transform );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif