29package com.jogamp.newt.javafx;
31import com.jogamp.common.util.PropertyAccess;
32import com.jogamp.common.util.locks.RecursiveLock;
33import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
34import com.jogamp.nativewindow.AbstractGraphicsScreen;
35import com.jogamp.nativewindow.Capabilities;
36import com.jogamp.nativewindow.CapabilitiesImmutable;
37import com.jogamp.nativewindow.GraphicsConfigurationFactory;
38import com.jogamp.nativewindow.NativeSurface;
39import com.jogamp.nativewindow.NativeWindow;
40import com.jogamp.nativewindow.NativeWindowException;
41import com.jogamp.nativewindow.NativeWindowFactory;
42import com.jogamp.nativewindow.NativeWindowHolder;
43import com.jogamp.nativewindow.SurfaceUpdatedListener;
44import com.jogamp.nativewindow.WindowClosingProtocol;
45import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode;
46import com.jogamp.nativewindow.util.Insets;
47import com.jogamp.nativewindow.util.InsetsImmutable;
48import com.jogamp.nativewindow.util.Point;
49import com.jogamp.nativewindow.util.Rectangle;
50import com.jogamp.opengl.GLCapabilities;
52import javafx.beans.value.ChangeListener;
53import javafx.beans.value.ObservableValue;
54import javafx.event.EventHandler;
55import javafx.geometry.Bounds;
56import javafx.scene.Scene;
57import javafx.scene.canvas.Canvas;
58import jogamp.newt.Debug;
59import jogamp.newt.javafx.JFXEDTUtil;
61import com.jogamp.nativewindow.javafx.JFXAccessor;
62import com.jogamp.newt.Display;
63import com.jogamp.newt.Window;
64import com.jogamp.newt.event.WindowEvent;
65import com.jogamp.newt.util.EDTUtil;
84 private static final boolean DEBUG = Debug.debug(
"Window");
85 private static final boolean USE_JFX_EDT = PropertyAccess.getBooleanProperty(
"jogamp.newt.javafx.UseJFXEDT",
true,
true);
86 private volatile javafx.stage.Window parentWindow =
null;
93 private volatile JFXNativeWindow nativeWindow =
null;
94 private volatile Window newtChild =
null;
95 private volatile boolean newtChildReady =
false;
96 private volatile boolean postSetSize =
false;
97 private volatile boolean postSetPos =
false;
99 private final EventHandler<javafx.stage.WindowEvent> windowClosingListener =
new EventHandler<javafx.stage.WindowEvent>() {
101 public final void handle(
final javafx.stage.WindowEvent e) {
103 System.err.println(
"NewtCanvasJFX.Event.DISPOSE, "+e+
", closeOp "+closingMode);
112 private final EventHandler<javafx.stage.WindowEvent> windowShownListener =
new EventHandler<javafx.stage.WindowEvent>() {
114 public final void handle(
final javafx.stage.WindowEvent e) {
116 System.err.println(
"NewtCanvasJFX.Event.SHOWN, "+e);
133 updateParentWindowAndScreen();
135 final ChangeListener<Number> sizeListener =
new ChangeListener<Number>() {
136 @Override
public void changed(
final ObservableValue<? extends Number> observable,
final Number oldValue,
final Number newValue) {
138 System.err.println(
"NewtCanvasJFX.Event.Size, "+oldValue.doubleValue()+
" -> "+newValue.doubleValue()+
", has "+getWidth()+
"x"+getHeight());
140 updateSizeCheck((
int)getWidth(), (
int)getHeight());
141 repaintAction(isVisible());
143 this.widthProperty().addListener(sizeListener);
144 this.heightProperty().addListener(sizeListener);
145 this.visibleProperty().addListener(
new ChangeListener<Boolean>() {
146 @Override
public void changed(
final ObservableValue<? extends Boolean> observable,
final Boolean oldValue,
final Boolean newValue) {
148 System.err.println(
"NewtCanvasJFX.Event.Visible, "+oldValue.booleanValue()+
" -> "+newValue.booleanValue()+
", has "+isVisible());
150 repaintAction(newValue.booleanValue());
153 this.sceneProperty().addListener(
new ChangeListener<Scene>() {
154 @Override
public void changed(
final ObservableValue<? extends Scene> observable,
final Scene oldValue,
final Scene newValue) {
156 System.err.println(
"NewtCanvasJFX.Event.Scene, "+oldValue+
" -> "+newValue+
", has "+getScene());
157 if(
null != newValue) {
158 final javafx.stage.Window w = newValue.getWindow();
159 System.err.println(
"NewtCanvasJFX.Event.Scene window "+w+
" (showing "+(
null!=w?w.isShowing():0)+
")");
162 if( updateParentWindowAndScreen() ) {
163 repaintAction(isVisible());
173 private final void repaintAction(
final boolean visible) {
174 if( visible && validateNative(
true ) ) {
175 if( newtChildReady ) {
189 private final void updatePosSizeCheck() {
190 final Bounds b = localToScene(getBoundsInLocal());
191 updatePosCheck((
int)b.getMinX(), (
int)b.getMinY());
192 updateSizeCheck((
int)getWidth(), (
int)getHeight());
194 private final void updatePosCheck(
final int newX,
final int newY) {
195 final boolean posChanged;
197 final Rectangle oClientArea = clientArea;
198 posChanged = newX != oClientArea.
getX() || newY != oClientArea.getY();
200 clientArea.
setX(newX);
201 clientArea.
setY(newY);
206 System.err.println(
"NewtCanvasJFX.updatePosCheck: posChanged "+posChanged+
", ("+Thread.currentThread().getName()+
"): newtChildReady "+newtChildReady+
", "+clientArea.
getX()+
"/"+clientArea.
getY()+
" "+clientArea.
getWidth()+
"x"+clientArea.
getHeight()+
" - surfaceHandle 0x"+Long.toHexString(nsh));
209 if( newtChildReady ) {
216 private final void updateSizeCheck(
final int newWidth,
final int newHeight) {
217 final boolean sizeChanged;
219 final Rectangle oClientArea = clientArea;
220 sizeChanged = newWidth != oClientArea.
getWidth() || newHeight != oClientArea.getHeight();
228 System.err.println(
"NewtCanvasJFX.updateSizeCheck: sizeChanged "+sizeChanged+
", ("+Thread.currentThread().getName()+
"): newtChildReady "+newtChildReady+
", "+clientArea.
getX()+
"/"+clientArea.
getY()+
" "+clientArea.
getWidth()+
"x"+clientArea.
getHeight()+
" - surfaceHandle 0x"+Long.toHexString(nsh));
231 if( newtChildReady ) {
239 private final ChangeListener<javafx.stage.Window> sceneWindowChangeListener =
new ChangeListener<javafx.stage.Window>() {
240 @Override
public void changed(
final ObservableValue<? extends javafx.stage.Window> observable,
final javafx.stage.Window oldValue,
final javafx.stage.Window newValue) {
242 System.err.println(
"NewtCanvasJFX.Event.Window, "+oldValue+
" -> "+newValue);
244 if( updateParentWindowAndScreen() ) {
245 repaintAction(isVisible());
249 private boolean updateParentWindowAndScreen() {
250 final Scene s = this.getScene();
252 final javafx.stage.Window w = s.getWindow();
254 System.err.println(
"NewtCanvasJFX.updateParentWindowAndScreen: Scene "+s+
", Window "+w+
" (showing "+(
null!=w?w.isShowing():0)+
")");
256 if( w != parentWindow ) {
261 screen = JFXAccessor.getScreen(JFXAccessor.getDevice(parentWindow), -1 );
262 parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener);
263 parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener);
266 s.windowProperty().addListener(sceneWindowChangeListener);
270 System.err.println(
"NewtCanvasJFX.updateParentWindowAndScreen: Null Scene");
272 if(
null != parentWindow ) {
296 private void destroyImpl(
final boolean disposeNewtChild) {
298 System.err.println(
"NewtCanvasJFX.dispose: (has parent "+(
null!=parentWindow)+
", hasNative "+(
null!=nativeWindow)+
",\n\t"+newtChild);
300 if(
null != newtChild ) {
304 if(
null != nativeWindow ) {
305 configureNewtChild(
false);
309 if( disposeNewtChild ) {
314 if(
null != parentWindow ) {
315 parentWindow.getScene().windowProperty().removeListener(sceneWindowChangeListener);
316 parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener);
317 parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener);
320 if(
null != screen ) {
327 private final boolean validateNative(
final boolean completeReparent) {
328 if(
null != nativeWindow ) {
331 if(
null == parentWindow ) {
334 updatePosSizeCheck();
338 final long nativeWindowHandle = JFXAccessor.getWindowHandle(parentWindow);
339 if( 0 == nativeWindowHandle ) {
345 final int visualID = JFXAccessor.getNativeVisualID(screen.
getDevice(), nativeWindowHandle);
346 final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
348 System.err.println(
"NewtCanvasJFX.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+
", visualID 0x"+Integer.toHexString(visualID)+
", valid "+visualIDValid);
350 if( visualIDValid ) {
353 final CapabilitiesImmutable caps =
new Capabilities();
354 final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.
getDevice(), caps);
355 final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps,
null, screen, visualID );
357 System.err.println(
"NewtCanvasJFX.validateNative() factory: "+factory+
", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+
", visualID 0x"+Integer.toHexString(visualID)+
", chosen config: "+config);
360 if (
null == config) {
361 throw new NativeWindowException(
"Error choosing GraphicsConfiguration creating window: "+
this);
364 nativeWindow =
new JFXNativeWindow(config, nativeWindowHandle);
365 if( completeReparent ) {
366 reparentWindow(
true );
370 return null != nativeWindow;
390 final Window prevChild = newtChild;
392 System.err.println(
"NewtCanvasJFX.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+
" -> "+newtWinHandleToHexString(newChild));
395 if(
null != newtChild) {
396 reparentWindow(
false );
400 newtChild = newChild;
401 if(
null != newtChild && validateNative(
false ) ) {
402 reparentWindow(
true );
407 private void reparentWindow(
final boolean add) {
408 if(
null == newtChild ) {
412 System.err.println(
"NewtCanvasJFX.reparentWindow.0: add="+add+
", win "+newtWinHandleToHexString(newtChild)+
", EDTUtil: cur "+newtChild.
getScreen().
getDisplay().
getEDTUtil());
417 assert
null != nativeWindow &&
null != parentWindow;
418 updatePosSizeCheck();
419 final int x = clientArea.
getX();
420 final int y = clientArea.
getY();
421 final int w = clientArea.
getWidth();
427 final EDTUtil oldEDTUtil = newtDisplay.
getEDTUtil();
428 if( ! ( oldEDTUtil instanceof JFXEDTUtil ) ) {
429 final EDTUtil newEDTUtil =
new JFXEDTUtil(newtDisplay);
431 System.err.println(
"NewtCanvasJFX.reparentWindow.1: replacing EDTUtil "+oldEDTUtil+
" -> "+newEDTUtil);
434 newtDisplay.setEDTUtil( newEDTUtil );
439 newtChild.
reparentWindow(nativeWindow, x, y, Window.REPARENT_HINT_BECOMES_VISIBLE);
442 configureNewtChild(
true);
449 configureNewtChild(
false);
454 System.err.println(
"NewtCanvasJFX.reparentWindow.X: add="+add+
", win "+newtWinHandleToHexString(newtChild)+
", EDTUtil: cur "+newtChild.
getScreen().
getDisplay().
getEDTUtil());
458 private void configureNewtChild(
final boolean attach) {
459 newtChildReady = attach;
460 if(
null != newtChild ) {
504 return null!=newtChild ;
507 boolean isFullscreen() {
511 private final void requestFocusNEWTChild() {
512 if( newtChildReady ) {
521 requestFocusNEWTChild();
526 private final long nativeWindowHandle;
530 this.config = config;
531 this.nativeWindowHandle = nativeWindowHandle;
532 this.insets =
new Insets(0, 0, 0, 0);
536 public RecursiveLock getLock() {
return null; }
539 public int lockSurface() throws NativeWindowException, RuntimeException {
540 return NativeSurface.LOCK_SUCCESS;
544 public void unlockSurface() { }
547 public boolean isSurfaceLockedByOtherThread() {
552 public Thread getSurfaceLockOwner() {
557 public boolean surfaceSwap() {
562 public void addSurfaceUpdatedListener(
final SurfaceUpdatedListener l) { }
565 public void addSurfaceUpdatedListener(
final int index,
final SurfaceUpdatedListener l)
throws IndexOutOfBoundsException {
569 public void removeSurfaceUpdatedListener(
final SurfaceUpdatedListener l) { }
572 public long getSurfaceHandle() {
587 public int getWidth() {
588 return getSurfaceWidth();
592 public int getHeight() {
593 return getSurfaceHeight();
597 public final Rectangle getBounds() {
598 return new Rectangle(getX(), getY(), getWidth(), getHeight());
602 public final Rectangle getSurfaceBounds() {
603 return new Rectangle(getX(), getY(),
604 getSurfaceWidth(), getSurfaceHeight());
608 public final int[] convertToWindowUnits(
final int[] pixelUnitsAndResult) {
609 return pixelUnitsAndResult;
613 public final int[] convertToPixelUnits(
final int[] windowUnitsAndResult) {
614 return windowUnitsAndResult;
618 public int getSurfaceWidth() {
623 public int getSurfaceHeight() {
631 public AbstractGraphicsConfiguration getGraphicsConfiguration() {
636 public long getDisplayHandle() {
641 public int getScreenIndex() {
646 public void surfaceUpdated(
final Object updater,
final NativeSurface ns,
final long when) { }
652 public NativeWindow getParent() {
657 public long getWindowHandle() {
658 return nativeWindowHandle;
662 public InsetsImmutable getInsets() {
667 public Point getLocationOnScreen(
final Point point) {
668 final Point los = NativeWindowFactory.getLocationOnScreen(
this);
670 return point.translate(los);
677 public boolean hasFocus() {
682 static String newtWinHandleToHexString(
final Window w) {
683 return null != w ? toHexString(w.getWindowHandle()) :
"nil";
685 static String toHexString(
final long l) {
686 return "0x"+Long.toHexString(l);
Mutable insets representing rectangular window decoration insets on all four edges in window units.
final int getX()
x-position, left of rectangle.
final Rectangle setWidth(final int width)
final int getY()
y-position, top of rectangle.
final Rectangle setY(final int y)
final Rectangle setHeight(final int height)
final Rectangle setX(final int x)
abstract EDTUtil getEDTUtil()
abstract Display getDisplay()
A NEWT based JFX Canvas specialization allowing a NEWT child Window to be attached using native paren...
WindowClosingMode getDefaultCloseOperation()
NewtCanvasJFX(final Window child)
Instantiates a NewtCanvas with a NEWT child.
void destroy()
Destroys this resource:
NativeWindow getNativeWindow()
Returns the associated NativeWindow of this NativeWindowHolder, which is identical to getNativeSurfac...
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
Window setNEWTChild(final Window newChild)
Sets a new NEWT child, provoking reparenting.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
Window closing mode if triggered by toolkit close operation.
DISPOSE_ON_CLOSE
Dispose resources on native window close operation.
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.
boolean close()
Optionally closing the device if handle is not null.
long getHandle()
Returns the native handle of the underlying native device, if such thing exist.
boolean open()
Optionally [re]opening the device if handle is null.
A interface describing a graphics screen in a toolkit-independent manner.
int getIndex()
Returns the screen index this graphics screen is valid for.
AbstractGraphicsDevice getDevice()
Return the device this graphics configuration is valid for.
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
long getSurfaceHandle()
Returns the handle to the surface for this NativeSurface.
Accessor interface for implementing classes with ownership of a NativeWindow via an is-a or has-a rel...
Extend the NativeSurface interface with windowing information such as window-handle,...
Protocol for handling window closing events.
WindowClosingMode setDefaultCloseOperation(WindowClosingMode op)
Immutable insets representing rectangular window decoration insets on all four edges in window units.
Specifying NEWT's Window functionality:
void sendWindowEvent(int eventType)
Send a WindowEvent to all WindowListener.
void setKeyboardFocusHandler(KeyListener l)
Sets a KeyListener allowing focus traversal with a covered window toolkit like AWT.
ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints)
Change this window's parent window.
boolean windowRepaint(int x, int y, int width, int height)
Trigger window repaint while passing the dirty region in pixel units.
void requestFocus()
Request focus for this native window.
void setFocusAction(FocusRunnable focusAction)
Sets a FocusRunnable, which FocusRunnable#run() method is executed before the native focus is request...
void setSize(int width, int height)
Sets the size of the window's client area in window units, excluding decorations.
void setVisible(boolean visible)
Calls setVisible(true, visible), i.e.
void setPosition(int x, int y)
Sets the location of the window's client area excluding insets (window decorations) in window units.
void destroy()
Destroys this window incl.releasing all related resources.