38package com.jogamp.nativewindow.awt;
40import com.jogamp.common.ExceptionUtils;
41import com.jogamp.common.os.Platform;
42import com.jogamp.common.util.awt.AWTEDTExecutor;
43import com.jogamp.common.util.locks.LockFactory;
44import com.jogamp.common.util.locks.RecursiveLock;
45import com.jogamp.nativewindow.MutableGraphicsConfiguration;
47import java.awt.Component;
48import java.awt.Container;
49import java.awt.Cursor;
50import java.awt.EventQueue;
51import java.awt.GraphicsConfiguration;
52import java.awt.event.ComponentEvent;
53import java.awt.event.ComponentListener;
54import java.awt.event.HierarchyEvent;
55import java.awt.event.HierarchyListener;
57import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
58import com.jogamp.nativewindow.AbstractGraphicsDevice;
59import com.jogamp.nativewindow.CapabilitiesImmutable;
60import com.jogamp.nativewindow.NativeSurface;
61import com.jogamp.nativewindow.NativeWindow;
62import com.jogamp.nativewindow.NativeWindowException;
63import com.jogamp.nativewindow.OffscreenLayerOption;
64import com.jogamp.nativewindow.OffscreenLayerSurface;
65import com.jogamp.nativewindow.ScalableSurface;
66import com.jogamp.nativewindow.SurfaceUpdatedListener;
67import com.jogamp.nativewindow.util.Insets;
68import com.jogamp.nativewindow.util.InsetsImmutable;
69import com.jogamp.nativewindow.util.PixelRectangle;
70import com.jogamp.nativewindow.util.Point;
71import com.jogamp.nativewindow.util.PointImmutable;
72import com.jogamp.nativewindow.util.Rectangle;
73import com.jogamp.nativewindow.util.RectangleImmutable;
75import jogamp.common.os.PlatformPropsImpl;
76import jogamp.nativewindow.SurfaceScaleUtils;
77import jogamp.nativewindow.SurfaceUpdatedHelper;
78import jogamp.nativewindow.awt.AWTMisc;
79import jogamp.nativewindow.jawt.JAWT;
80import jogamp.nativewindow.jawt.JAWTUtil;
81import jogamp.nativewindow.jawt.JAWT_Rectangle;
84 protected static final boolean DEBUG = JAWTUtil.DEBUG;
92 private final SurfaceUpdatedHelper surfaceUpdatedHelper =
new SurfaceUpdatedHelper();
93 private final RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
94 private final JAWTComponentListener jawtComponentListener;
99 private boolean isOffscreenLayerSurface;
103 private volatile long offscreenSurfaceLayer;
106 private volatile boolean hasPixelScaleChanged =
false;
107 private long drawable_old;
117 if (config ==
null) {
118 throw new IllegalArgumentException(
"Error: AbstractGraphicsConfiguration is null");
121 throw new NativeWindowException(
"Error: AbstractGraphicsConfiguration is not an AWTGraphicsConfiguration: "+config);
123 if( JAWTUtil.isOffscreenLayerSupported() ) {
126 appContextInfo =
null;
128 this.component = (Component)comp;
129 this.jawtComponentListener =
new JAWTComponentListener();
130 this.offscreenSurfaceLayer = 0;
134 System.err.println(jawtStr2(
"ctor"));
137 private static String id(
final Object obj) {
return (
null!=obj ?
toHexString(obj.hashCode()) :
"nil" ); }
138 private String jawtStr1() {
return "JAWTWindow["+id(
JAWTWindow.this)+
"]"; }
139 private String jawtStr2(
final String sub) {
return jawtStr1()+
"."+sub+
" @ Thread "+getThreadName(); }
141 private class JAWTComponentListener
implements ComponentListener, HierarchyListener {
142 private volatile boolean isShowing;
144 private String str(
final Object obj) {
146 return "0xnil: null";
147 }
else if( obj instanceof Component ) {
148 final Component c = (Component)obj;
149 return id(obj)+
": "+c.getClass().getSimpleName()+
"[visible "+c.isVisible()+
", showing "+c.isShowing()+
", valid "+c.isValid()+
150 ", displayable "+c.isDisplayable()+
", "+c.getX()+
"/"+c.getY()+
" "+c.getWidth()+
"x"+c.getHeight()+
"]";
152 return id(obj)+
": "+obj.getClass().getSimpleName()+
"[..]";
155 private String s(
final ComponentEvent e) {
156 return "visible[isShowing "+isShowing+
"],"+Platform.getNewline()+
157 " ** COMP "+str(e.getComponent())+Platform.getNewline()+
158 " ** SOURCE "+str(e.getSource())+Platform.getNewline()+
159 " ** THIS "+str(
component)+Platform.getNewline()+
160 " ** THREAD "+getThreadName();
162 private String s(
final HierarchyEvent e) {
163 return "visible[isShowing "+isShowing+
"], changeBits 0x"+Long.toHexString(e.getChangeFlags())+Platform.getNewline()+
164 " ** COMP "+str(e.getComponent())+Platform.getNewline()+
165 " ** SOURCE "+str(e.getSource())+Platform.getNewline()+
166 " ** CHANGED "+str(e.getChanged())+Platform.getNewline()+
167 " ** CHANGEDPARENT "+str(e.getChangedParent())+Platform.getNewline()+
168 " ** THIS "+str(
component)+Platform.getNewline()+
169 " ** THREAD "+getThreadName();
173 return "visible[isShowing "+isShowing+
"],"+Platform.getNewline()+
174 " ** THIS "+str(
component)+Platform.getNewline()+
175 " ** THREAD "+getThreadName();
178 private JAWTComponentListener() {
180 AWTEDTExecutor.singleton.invoke(
false,
new Runnable() {
185 System.err.println(jawtStr2(
"attach")+
": "+JAWTComponentListener.this.toString());
187 component.addComponentListener(JAWTComponentListener.this);
188 component.addHierarchyListener(JAWTComponentListener.this);
192 private final void detach() {
193 AWTEDTExecutor.singleton.invoke(
false,
new Runnable() {
197 System.err.println(jawtStr2(
"detach")+
": "+JAWTComponentListener.this.toString());
199 component.removeComponentListener(JAWTComponentListener.this);
200 component.removeHierarchyListener(JAWTComponentListener.this);
205 public final void componentResized(
final ComponentEvent e) {
207 System.err.println(jawtStr2(
"componentResized")+
": "+s(e));
209 layoutSurfaceLayerIfEnabled(isShowing);
213 public final void componentMoved(
final ComponentEvent e) {
215 System.err.println(jawtStr2(
"componentMoved")+
": "+s(e));
217 layoutSurfaceLayerIfEnabled(isShowing);
221 public final void componentShown(
final ComponentEvent e) {
223 System.err.println(jawtStr2(
"componentShown")+
": "+s(e));
225 layoutSurfaceLayerIfEnabled(isShowing);
229 public final void componentHidden(
final ComponentEvent e) {
231 System.err.println(jawtStr2(
"componentHidden")+
": "+s(e));
233 layoutSurfaceLayerIfEnabled(isShowing);
237 public final void hierarchyChanged(
final HierarchyEvent e) {
238 final boolean wasShowing = isShowing;
241 if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags() ) ) {
242 if( e.getChanged() !=
component && wasShowing != isShowing ) {
245 layoutSurfaceLayerIfEnabled(isShowing);
250 final java.awt.Component changed = e.getChanged();
251 final boolean displayable = changed.isDisplayable();
252 final boolean showing = changed.isShowing();
253 System.err.println(jawtStr2(
"hierarchyChanged")+
": action "+action+
", displayable "+displayable+
", showing [changed "+showing+
", comp "+wasShowing+
" -> "+isShowing+
"], "+s(e));
258 private static String getThreadName() {
return Thread.currentThread().getName(); }
262 System.err.println(jawtStr2(
"invalidate")+
" - "+jawtComponentListener.toString());
264 System.err.println(
"OffscreenSurfaceLayer still attached: 0x"+Long.toHexString(offscreenSurfaceLayer));
269 final long osl = offscreenSurfaceLayer;
270 offscreenSurfaceLayer = 0;
275 offscreenSurfaceLayer = 0;
276 isOffscreenLayerSurface =
false;
283 hasPixelScaleChanged =
false;
301 System.err.println(jawtStr2(
"setAWTGraphicsConfiguration")+
": "+this.awtConfig+
" -> "+config);
304 if(
null == awtConfig ) {
305 throw new IllegalArgumentException(jawtStr2(
"")+
": null config");
307 this.awtConfig = config;
353 System.arraycopy(hasPixelScale, 0, result, 0, 2);
378 System.arraycopy(hasPixelScale, 0, result, 0, 2);
387 protected final boolean updateLockedData(
final JAWT_Rectangle jawtBounds,
final GraphicsConfiguration gc) {
388 final Rectangle jb =
new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight());
391 if( changedBounds ) {
395 jawt_surface_bounds.
set(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight());
398 final java.awt.Insets contInsets = ((Container)
component).getInsets();
399 insets.
set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
404 return hasPixelScaleChanged || changedBounds;
419 public final boolean updatePixelScale(
final GraphicsConfiguration gc,
final boolean clearFlag) {
420 final float[] min = { 1, 1 };
421 final float[] max = { hasPixelScale[0], hasPixelScale[1] };
422 if( JAWTUtil.getPixelScale(gc, min, max) ) {
425 System.err.println(
"JAWTWindow.updatePixelScale: ["+hasPixelScale[0]+
", "+hasPixelScale[1]+
"] -> ["+max[0]+
", "+max[1]+
"]");
427 hasPixelScaleChanged =
true;
428 System.arraycopy(max, 0, hasPixelScale, 0, 2);
431 final boolean r = hasPixelScaleChanged;
432 hasPixelScaleChanged =
false;
435 return hasPixelScaleChanged;
451 final boolean v = hasPixelScaleChanged;
452 hasPixelScaleChanged =
false;
504 return isOffscreenLayerSurface;
513 if(
null == appContextInfo ) {
520 offscreenSurfaceLayer = layerHandle;
523 private final Runnable repaintTask =
new Runnable() {
528 System.err.println(
"Bug 1004: RepaintTask on "+Thread.currentThread()+
": Has Comp "+(
null != c));
536 throw new UnsupportedOperationException(
"offscreen layer not supported");
563 if( 0 == offscreenSurfaceLayer) {
567 System.err.println(
"JAWTWindow.detachSurfaceHandle(): osh "+
toHexString(offscreenSurfaceLayer)+
" - "+Thread.currentThread().getName());
570 final long osl = offscreenSurfaceLayer;
571 offscreenSurfaceLayer = 0;
580 throw new UnsupportedOperationException(
"offscreen layer not supported");
586 return offscreenSurfaceLayer;
591 return 0 != offscreenSurfaceLayer;
607 AWTEDTExecutor.singleton.invoke(
false,
new Runnable() {
611 if(
null == pixelrect ||
null == hotSpot ) {
612 c = Cursor.getDefaultCursor();
614 final java.awt.Point awtHotspot =
new java.awt.Point(hotSpot.
getX(), hotSpot.
getY());
616 c = AWTMisc.getCursor(pixelrect, awtHotspot);
617 }
catch (
final Exception e) {
630 AWTEDTExecutor.singleton.invoke(
false,
new Runnable() {
633 final Cursor cursor = AWTMisc.getNullCursor();
634 if(
null != cursor ) {
680 surfaceLock.unlock();
682 System.err.println(
"JAWTWindow: Can't lock surface, component peer n/a. Component displayable "+
component.isDisplayable()+
", "+
component);
683 ExceptionUtils.dumpStack(System.err);
686 final GraphicsConfiguration gc;
687 if( EventQueue.isDispatchThread() || Thread.holdsLock(
component.getTreeLock()) ) {
693 gc =
component.getGraphicsConfiguration();
706 isOffscreenLayerSurface = JAWTUtil.isJAWTUsingOffscreenLayer(jawt);
723 surfaceLock.unlock();
735 surfaceLock.validateLocked();
738 if (surfaceLock.getHoldCount() == 1) {
748 surfaceLock.unlock();
753 return surfaceLock.isLockedByOtherThread();
758 return surfaceLock.getOwner();
768 surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
773 surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
778 surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
783 surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
793 if(
null == awtConfig ) {
821 return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale);
826 return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale);
873 System.err.println(jawtStr2(
"destroy"));
875 jawtComponentListener.detach();
878 surfaceLock.unlock();
919 System.err.println(
"Warning: JAWT Lock couldn't be acquired: "+
this);
920 ExceptionUtils.dumpStack(System.err);
946 sb =
new StringBuilder();
948 sb.append(
"JVM version: ").append(PlatformPropsImpl.JAVA_VERSION).append(
" (").
949 append(PlatformPropsImpl.JAVA_VERSION_NUMBER).
950 append(
" update ").append(PlatformPropsImpl.JAVA_VERSION_UPDATE).append(
")").append(Platform.getNewline());
952 sb.append(
"JAWT version: ").append(
toHexString(jawt.getCachedVersion())).
953 append(
", CA_LAYER: ").append(JAWTUtil.isJAWTUsingOffscreenLayer(jawt)).
965 final StringBuilder sb =
new StringBuilder();
967 sb.append(jawtStr1()+
"[");
969 sb.append(
", shallUseOffscreenLayer "+
shallUseOffscreenLayer+
", isOffscreenLayerSurface "+isOffscreenLayerSurface+
979 ",\n\tconfig "+awtConfig+
981 ",\n\tsurfaceLock "+surfaceLock+
"]");
983 return sb.toString();
987 return "0x"+Long.toHexString(l);
990 return "0x"+Integer.toHexString(i);
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
A wrapper for an AWT GraphicsConfiguration allowing it to be handled in a toolkit-independent manner.
GraphicsConfiguration getAWTGraphicsConfiguration()
Return the AWT GraphicsConfiguration.
AbstractGraphicsConfiguration getNativeGraphicsConfiguration()
In case the implementation utilizes a delegation pattern to wrap abstract toolkits,...
void setChosenCapabilities(final CapabilitiesImmutable capsChosen)
Set the capabilities to a new value.
Instance of this class holds information about a ThreadGroup associated sun.awt.AppContext.
RunnableTask invokeOnAppContextThread(final boolean waitUntilDone, final Runnable runnable, final String threadBaseName)
Invokes runnable on a Thread belonging to the sun.awt.AppContext ThreadGroup, see getCachedThreadGrou...
final AbstractGraphicsConfiguration getGraphicsConfiguration()
Returns the graphics configuration corresponding to this window.
final boolean hasPixelScaleChanged()
Returns and clears the hasPixelScaleChanged flag, as set via lockSurface().
final int getY()
Returns the current y position of the top-left corner of the client area relative to it's parent in w...
abstract void invalidateNative(final long _offscreenSurfaceLayer)
final int[] convertToWindowUnits(final int[] pixelUnitsAndResult)
Converts the given pixel units into window units in place.
StringBuilder jawt2String(StringBuilder sb)
abstract void unlockSurfaceImpl()
boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
final void attachSurfaceLayer(final long layerHandle)
Attach the offscreen layer to this offscreen layer surface.
final boolean updateLockedData(final JAWT_Rectangle jawtBounds, final GraphicsConfiguration gc)
Updates bounds and pixelScale.
final RectangleImmutable getJAWTSurfaceBounds()
final int getSurfaceHeight()
Returns the height of the client area excluding insets (window decorations) in pixel units.
abstract Point getLocationOnScreenNativeImpl(int x, int y)
final JAWT getJAWT()
Returns the underlying JAWT instance created @ lockSurface().
boolean surfaceSwap()
Provide a mechanism to utilize custom (pre-) swap surface code.
static final boolean DEBUG
final int getWidth()
Returns the width of the client area excluding insets (window decorations) in window units.
void detachSurfaceLayerImpl(final long _offscreenSurfaceLayer)
final boolean canSetSurfaceScale()
Returns true if setSurfaceScale(float[]) is supported, otherwise false.For pure downstream scalable s...
synchronized void invalidate()
abstract JAWT fetchJAWTImpl()
private void determineIfApplet() { boolean isApplet = false; // dummy Component c = component; while(...
boolean hasFocus()
Returns true if this native window owns the focus, otherwise false.
long getWindowHandle()
Returns the window handle for this NativeWindow.
static final String toHexString(final long l)
final long getDisplayHandle()
Convenience: Get display handle from AbstractGraphicsConfiguration .
final boolean isSurfaceLayerAttached()
Returns true if a surface layer is attached, otherwise false.
final float[] getCurrentSurfaceScale(final float[] result)
Returns the current pixel scale of the associated NativeSurface.
final void detachSurfaceLayer()
Detaches a previously attached offscreen layer from this offscreen layer surface.
final Rectangle getSurfaceBounds()
Returns a newly created Rectangle containing window's surface origin and size in pixel units.
final RecursiveLock getLock()
Returns the recursive lock object of this surface, which synchronizes multithreaded access.
JAWTWindow(final Object comp, final AbstractGraphicsConfiguration config)
Constructed by jogamp.nativewindow.NativeWindowFactoryImpl#getNativeWindow(Object,...
final int getScreenIndex()
Convenience: Get display handle from AbstractGraphicsConfiguration .
final Thread getSurfaceLockOwner()
Return the locking owner's Thread, or null if not locked.
long getSurfaceHandle()
Returns the handle to the surface for this NativeSurface.
Point getLocationOnScreenNative(final Point storage)
final boolean isApplet()
Return false since there is no more java.applet.Applet support.
abstract int lockSurfaceImpl(GraphicsConfiguration gc)
final boolean setCursor(final PixelRectangle pixelrect, final PointImmutable hotSpot)
Optional method setting cursor in the corresponding on-screen surface/window, if exists.
final boolean hideCursor()
Optional method hiding the cursor in the corresponding on-screen surface/window, if exists.
final float getPixelScaleY()
Rectangle jawt_surface_bounds
void addSurfaceUpdatedListener(final SurfaceUpdatedListener l)
Appends the given SurfaceUpdatedListener to the end of the list.
Point getLocationOnScreen(final Point storage)
Returns the window's top-left client-area position in the screen.If Point is not null,...
void destroy()
Destroys this window incl.
final long getAttachedSurfaceLayer()
Returns the attached surface layer or null if none is attached.
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
final int getHeight()
Returns the height of the client area excluding insets (window decorations) in window units.
final int lockSurface()
Lock the surface of this native window.
final Component component
final float[] getRequestedSurfaceScale(final float[] result)
Returns the requested pixel scale of the associated NativeSurface.If canSetSurfaceScale() returns fal...
final Rectangle getBounds()
Returns a newly created Rectangle containing window origin, getX() & getY(), and size,...
static final String toHexString(final int i)
final void setChosenCapabilities(final CapabilitiesImmutable caps)
Sets the capabilities of this instance, allowing upstream API's to refine it, i.e.
void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l)
Remove the specified SurfaceUpdatedListener from the list.
float[] getMinimumSurfaceScale(final float[] result)
Returns the minimum pixel scale of the associated NativeSurface.the passed storage containing the min...
final int getX()
Returns the current x position of this window, relative to it's parent.
void layoutSurfaceLayerImpl(final boolean visible)
Layout the offscreen layer according to the implementing class's constraints.
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
final int getSurfaceWidth()
Returns the width of the client area excluding insets (window decorations) in pixel units.
void surfaceUpdated(final Object updater, final NativeSurface ns, final long when)
Notification of a surface update event, eg.
final AWTGraphicsConfiguration getAWTGraphicsConfiguration()
Return the current AWTGraphicsConfiguration instance, which also holds its upstream component's Graph...
void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l)
Inserts the given SurfaceUpdatedListener at the specified position in the list.
final boolean getShallUseOffscreenLayer()
Returns the property set by setShallUseOffscreenLayer(boolean).
final float[] getMaximumSurfaceScale(final float[] result)
Returns the maximum pixel scale of the associated NativeSurface.The maximum pixel scale maybe used to...
final NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.Returns this instance,...
final void unlockSurface()
Unlock the surface of this native window.
final InsetsImmutable getInsets()
Returns the insets defined as the width and height of the window decoration on the left,...
boolean shallUseOffscreenLayer
final boolean updatePixelScale(final GraphicsConfiguration gc, final boolean clearFlag)
Updates the minimum and maximum pixel-scale values and returns true if they were updated.
final int[] convertToPixelUnits(final int[] windowUnitsAndResult)
Converts the given window units into pixel units in place.
final NativeWindow getParent()
final float getPixelScaleX()
void attachSurfaceLayerImpl(final long _offscreenSurfaceLayer)
final Component getAWTComponent()
final boolean isSurfaceLockedByOtherThread()
Query if surface is locked by another thread, i.e.
final void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config)
Set a new AWTGraphicsConfiguration instance, as required if upstream component's GraphicsConfiguratio...
Mutable insets representing rectangular window decoration insets on all four edges in window units.
final void set(final int left, final int right, final int top, final int bottom)
Set the inset values of this instance in window units.
final Point translate(final Point pd)
Translate this instance's x- and y-components, i.e.
final Rectangle set(final int x, final int y, final int width, final int height)
boolean equals(final Object obj)
Checks whether two rect objects are equal.
A marker interface describing a graphics configuration, visual, or pixel format in a toolkit-independ...
AbstractGraphicsScreen getScreen()
Return the screen this graphics configuration is valid for.
A interface describing a graphics device in a toolkit-independent manner.
void lock()
Optionally locking the device, utilizing eg com.jogamp.nativewindow.ToolkitLock#lock().
void unlock()
Optionally unlocking the device, utilizing eg com.jogamp.nativewindow.ToolkitLock#unlock().
long getHandle()
Returns the native handle of the underlying native device, if such thing exist.
int getIndex()
Returns the screen index this graphics screen is valid for.
AbstractGraphicsDevice getDevice()
Return the device this graphics configuration is valid for.
Specifies an immutable set of capabilities that a window's rendering context must support,...
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
static final int LOCK_SURFACE_NOT_READY
Returned by lockSurface() if the surface is not ready to be locked, {@value}.
static final int LOCK_SURFACE_CHANGED
Returned by lockSurface() if the surface is locked, but has changed, {@value}.
static final int LOCK_SUCCESS
Returned by lockSurface() if the surface is locked, and is unchanged, {@value}.
Extend the NativeSurface interface with windowing information such as window-handle,...
Handling requests for using an OffscreenLayerSurface within the implementation.
Interface specifying the offscreen layer surface protocol.
Adding mutable surface pixel scale property to implementing class, usually to a NativeSurface impleme...
static final float IDENTITY_PIXELSCALE
Setting surface-pixel-scale of {@value}, results in same pixel- and window-units.
static final float AUTOMAX_PIXELSCALE
Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale,...
Clients may add their SurfaceUpdateListener implementation to a com.jogamp.nativewindow....
Immutable insets representing rectangular window decoration insets on all four edges in window units.
Pixel Rectangle identified by it's hashCode().
Immutable Point interface.
Immutable Rectangle interface, with its position on the top-left.