aboutsummaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2012-03-06 07:27:29 +0100
committerSven Gothel <[email protected]>2012-03-06 07:27:29 +0100
commit28ca3652c7c3c73cc3c41ad84b3f1efdad98add5 (patch)
tree20c687ec4b4ef1be7ff3548c96e1913889e3be8b /src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
parent9124f3fade3f923b581c6e7b871d049b431bbd78 (diff)
NativeWindow public-spec to public-impl reorg (javax.media.nativewindow.<impl> -> com.jogamp.nativewindow.<impl>) 1/2
Diffstat (limited to 'src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java489
1 files changed, 489 insertions, 0 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
new file mode 100644
index 000000000..863b336fc
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -0,0 +1,489 @@
+/*
+ * 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
+ * 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.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package jogamp.nativewindow.jawt;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.applet.Applet;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.OffscreenLayerOption;
+import javax.media.nativewindow.OffscreenLayerSurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.awt.AWTGraphicsConfiguration;
+import javax.media.nativewindow.util.Insets;
+import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
+
+import jogamp.nativewindow.SurfaceUpdatedHelper;
+
+public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, OffscreenLayerOption {
+ protected static final boolean DEBUG = JAWTUtil.DEBUG;
+
+ // user properties
+ protected boolean shallUseOffscreenLayer = false;
+
+ // lifetime: forever
+ protected Component component;
+ private AWTGraphicsConfiguration config; // control access due to delegation
+ private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+
+ // lifetime: valid after lock but may change with each 1st lock, purges after invalidate
+ private boolean isApplet;
+ private JAWT jawt;
+ private boolean isOffscreenLayerSurface;
+ protected long drawable;
+ protected Rectangle bounds;
+ protected Insets insets;
+
+ private long drawable_old;
+
+ /**
+ * Constructed by {@link jogamp.nativewindow.NativeWindowFactoryImpl#getNativeWindow(Object, AbstractGraphicsConfiguration)}
+ * via this platform's specialization (X11, OSX, Windows, ..).
+ *
+ * @param comp
+ * @param config
+ */
+ protected JAWTWindow(Object comp, AbstractGraphicsConfiguration config) {
+ if (config == null) {
+ throw new NativeWindowException("Error: AbstractGraphicsConfiguration is null");
+ }
+ if(! ( config instanceof AWTGraphicsConfiguration ) ) {
+ throw new NativeWindowException("Error: AbstractGraphicsConfiguration is not an AWTGraphicsConfiguration: "+config);
+ }
+ this.config = (AWTGraphicsConfiguration) config;
+ init((Component)comp);
+ }
+
+ private void init(Component windowObject) throws NativeWindowException {
+ invalidate();
+ this.component = windowObject;
+ this.isApplet = false;
+ }
+
+ public void setShallUseOffscreenLayer(boolean v) {
+ shallUseOffscreenLayer = v;
+ }
+
+ public final boolean getShallUseOffscreenLayer() {
+ return shallUseOffscreenLayer;
+ }
+
+ public final boolean isOffscreenLayerSurfaceEnabled() {
+ return isOffscreenLayerSurface;
+ }
+
+ protected synchronized void invalidate() {
+ invalidateNative();
+ jawt = null;
+ isOffscreenLayerSurface = false;
+ drawable= 0;
+ drawable_old = 0;
+ bounds = new Rectangle();
+ insets = new Insets();
+ }
+ protected abstract void invalidateNative();
+
+ protected final void updateBounds(JAWT_Rectangle jawtBounds) {
+ bounds.setX(jawtBounds.getX());
+ bounds.setY(jawtBounds.getY());
+ bounds.setWidth(jawtBounds.getWidth());
+ bounds.setHeight(jawtBounds.getHeight());
+
+ if(component instanceof Container) {
+ java.awt.Insets contInsets = ((Container)component).getInsets();
+ insets.setLeftWidth(contInsets.left);
+ insets.setRightWidth(contInsets.right);
+ insets.setTopHeight(contInsets.top);
+ insets.setBottomHeight(contInsets.bottom);
+ }
+ }
+
+ /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */
+ public final RectangleImmutable getBounds() { return bounds; }
+
+ public final InsetsImmutable getInsets() { return insets; }
+
+ public final Component getAWTComponent() {
+ return component;
+ }
+
+ /**
+ * Returns true if the AWT component is parented to an {@link java.applet.Applet},
+ * otherwise false. This information is valid only after {@link #lockSurface()}.
+ */
+ public final boolean isApplet() {
+ return isApplet;
+ }
+
+ /** Returns the underlying JAWT instance created @ {@link #lockSurface()}. */
+ public final JAWT getJAWT() {
+ return jawt;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void attachSurfaceLayer(final long layerHandle) throws NativeWindowException {
+ if( !isOffscreenLayerSurfaceEnabled() ) {
+ throw new NativeWindowException("Not an offscreen layer surface");
+ }
+ int lockRes = lockSurface();
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ throw new NativeWindowException("Could not lock (offscreen layer): "+this);
+ }
+ try {
+ if(DEBUG) {
+ System.err.println("JAWTWindow.attachSurfaceHandle(): 0x"+Long.toHexString(layerHandle));
+ }
+ attachSurfaceLayerImpl(layerHandle);
+ } finally {
+ unlockSurface();
+ }
+ }
+ protected abstract void attachSurfaceLayerImpl(final long layerHandle);
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void detachSurfaceLayer(final long layerHandle) throws NativeWindowException {
+ if( !isOffscreenLayerSurfaceEnabled() ) {
+ throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
+ }
+ int lockRes = lockSurface();
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ throw new NativeWindowException("Could not lock (offscreen layer): "+this);
+ }
+ try {
+ if(DEBUG) {
+ System.err.println("JAWTWindow.detachSurfaceHandle(): 0x"+Long.toHexString(layerHandle));
+ }
+ detachSurfaceLayerImpl(layerHandle);
+ } finally {
+ unlockSurface();
+ }
+ }
+ protected abstract void detachSurfaceLayerImpl(final long layerHandle);
+
+ //
+ // SurfaceUpdateListener
+ //
+
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ }
+
+ //
+ // NativeSurface
+ //
+
+ private void determineIfApplet() {
+ Component c = component;
+ while(!isApplet && null != c) {
+ isApplet = c instanceof Applet;
+ c = c.getParent();
+ }
+ }
+
+ /**
+ * If JAWT offscreen layer is supported,
+ * implementation shall respect {@link #getShallUseOffscreenLayer()}
+ * and may respect {@link #isApplet()}.
+ *
+ * @return The JAWT instance reflecting offscreen layer support, etc.
+ *
+ * @throws NativeWindowException
+ */
+ protected abstract JAWT fetchJAWTImpl() throws NativeWindowException;
+ protected abstract int lockSurfaceImpl() throws NativeWindowException;
+
+ protected void dumpJAWTInfo() {
+ if(null != jawt) {
+ System.err.println("JAWT version: 0x"+Integer.toHexString(jawt.getCachedVersion())+
+ ", CA_LAYER: "+ JAWTUtil.isJAWTUsingOffscreenLayer(jawt)+
+ ", isLayeredSurface "+isOffscreenLayerSurfaceEnabled()+", bounds "+bounds+", insets "+insets);
+ } else {
+ System.err.println("JAWT n/a, bounds "+bounds+", insets "+insets);
+ }
+ // Thread.dumpStack();
+ }
+
+ public final int lockSurface() throws NativeWindowException {
+ surfaceLock.lock();
+ int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+
+ if ( LOCK_SURFACE_NOT_READY == res ) {
+ determineIfApplet();
+ try {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ adevice.lock();
+ try {
+ jawt = fetchJAWTImpl();
+ isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
+ res = lockSurfaceImpl();
+ if(LOCK_SUCCESS == res && drawable_old != drawable) {
+ res = LOCK_SURFACE_CHANGED;
+ if(DEBUG) {
+ System.err.println("JAWTWindow: surface change 0x"+Long.toHexString(drawable_old)+" -> 0x"+Long.toHexString(drawable));
+ // Thread.dumpStack();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ adevice.unlock();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ surfaceLock.unlock();
+ }
+ }
+ }
+ return res;
+ }
+
+ protected abstract void unlockSurfaceImpl() throws NativeWindowException;
+
+ public final void unlockSurface() {
+ surfaceLock.validateLocked();
+ drawable_old = drawable;
+
+ if (surfaceLock.getHoldCount() == 1) {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ try {
+ unlockSurfaceImpl();
+ } finally {
+ adevice.unlock();
+ }
+ }
+ surfaceLock.unlock();
+ }
+
+ public final boolean isSurfaceLockedByOtherThread() {
+ return surfaceLock.isLockedByOtherThread();
+ }
+
+ public final boolean isSurfaceLocked() {
+ return surfaceLock.isLocked();
+ }
+
+ public final Thread getSurfaceLockOwner() {
+ return surfaceLock.getOwner();
+ }
+
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ public long getSurfaceHandle() {
+ return drawable;
+ }
+
+ public final AWTGraphicsConfiguration getPrivateGraphicsConfiguration() {
+ return config;
+ }
+
+ public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config.getNativeGraphicsConfiguration();
+ }
+
+ public final long getDisplayHandle() {
+ return getGraphicsConfiguration().getScreen().getDevice().getHandle();
+ }
+
+ public final int getScreenIndex() {
+ return getGraphicsConfiguration().getScreen().getIndex();
+ }
+
+ public int getWidth() {
+ return component.getWidth();
+ }
+
+ public int getHeight() {
+ return component.getHeight();
+ }
+
+ //
+ // NativeWindow
+ //
+
+ public synchronized void destroy() {
+ invalidate();
+ component = null; // don't dispose the AWT component, since we are merely an immutable uplink
+ }
+
+ public final NativeWindow getParent() {
+ return null;
+ }
+
+ public long getWindowHandle() {
+ return drawable;
+ }
+
+ public final int getX() {
+ return component.getX();
+ }
+
+ public final int getY() {
+ return component.getY();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * This JAWT default implementation is currently still using
+ * a blocking implementation. It first attempts to retrieve the location
+ * via a native implementation. If this fails, it tries the blocking AWT implementation.
+ * If the latter fails due to an external AWT tree-lock, the non block
+ * implementation {@link #getLocationOnScreenNonBlocking(Point, Component)} is being used.
+ * The latter simply traverse up to the AWT component tree and sums the rel. position.
+ * We have to determine whether the latter is good enough for all cases,
+ * currently only OS X utilizes the non blocking method per default.
+ * </p>
+ */
+ public Point getLocationOnScreen(Point storage) {
+ Point los = getLocationOnScreenNative(storage);
+ if(null == los) {
+ if(!Thread.holdsLock(component.getTreeLock())) {
+ // avoid deadlock ..
+ if(DEBUG) {
+ System.err.println("Warning: JAWT Lock hold, but not the AWT tree lock: "+this);
+ Thread.dumpStack();
+ }
+ return getLocationOnScreenNonBlocking(storage, component);
+ }
+ java.awt.Point awtLOS = component.getLocationOnScreen();
+ if(null!=storage) {
+ los = storage.translate(awtLOS.x, awtLOS.y);
+ } else {
+ los = new Point(awtLOS.x, awtLOS.y);
+ }
+ }
+ return los;
+ }
+
+ protected Point getLocationOnScreenNative(Point storage) {
+ int lockRes = lockSurface();
+ if(LOCK_SURFACE_NOT_READY == lockRes) {
+ if(DEBUG) {
+ System.err.println("Warning: JAWT Lock couldn't be acquired: "+this);
+ Thread.dumpStack();
+ }
+ return null;
+ }
+ try {
+ Point d = getLocationOnScreenNativeImpl(0, 0);
+ if(null!=d) {
+ if(null!=storage) {
+ storage.translate(d.getX(),d.getY());
+ return storage;
+ }
+ }
+ return d;
+ } finally {
+ unlockSurface();
+ }
+ }
+ protected abstract Point getLocationOnScreenNativeImpl(int x, int y);
+
+ protected static Point getLocationOnScreenNonBlocking(Point storage, Component comp) {
+ int x = 0;
+ int y = 0;
+ while(null != comp) {
+ x += comp.getX();
+ y += comp.getY();
+ comp = comp.getParent();
+ }
+ if(null!=storage) {
+ storage.translate(x, y);
+ return storage;
+ }
+ return new Point(x, y);
+ }
+
+ public boolean hasFocus() {
+ return component.hasFocus();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("JAWT-Window["+
+ "windowHandle 0x"+Long.toHexString(getWindowHandle())+
+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
+ ", bounds "+bounds+", insets "+insets+
+ ", shallUseOffscreenLayer "+shallUseOffscreenLayer+", isOffscreenLayerSurface "+isOffscreenLayerSurface);
+ if(null!=component) {
+ sb.append(", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
+ ", visible "+component.isVisible());
+ } else {
+ sb.append(", component NULL");
+ }
+ sb.append(", lockedExt "+isSurfaceLockedByOtherThread()+
+ ",\n\tconfig "+getPrivateGraphicsConfiguration()+
+ ",\n\tawtComponent "+getAWTComponent()+
+ ",\n\tsurfaceLock "+surfaceLock+"]");
+
+ return sb.toString();
+ }
+
+}