diff options
Diffstat (limited to 'src/newt/classes/com')
7 files changed, 350 insertions, 54 deletions
diff --git a/src/newt/classes/com/sun/javafx/newt/Window.java b/src/newt/classes/com/sun/javafx/newt/Window.java index 10a31f451..c2ab88b32 100755 --- a/src/newt/classes/com/sun/javafx/newt/Window.java +++ b/src/newt/classes/com/sun/javafx/newt/Window.java @@ -247,7 +247,7 @@ public abstract class Window implements NativeWindow public synchronized void destroy() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() start"); + System.out.println("Window.destroy() start "+Thread.currentThread().getName()); } windowListeners = new ArrayList(); mouseListeners = new ArrayList(); @@ -255,15 +255,15 @@ public abstract class Window implements NativeWindow closeNative(); invalidate(); if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() end"); + System.out.println("Window.destroy() end "+Thread.currentThread().getName()); } } public void invalidate() { - invalidate(false); - } - - public void invalidate(boolean internal) { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread().getName()); + e.printStackTrace(); + } screen = null; windowHandle = 0; fullscreen=false; @@ -297,6 +297,13 @@ public abstract class Window implements NativeWindow return windowHandle; // default: return window handle } + /** Special method to dispose a surface handle, + in case of a device change _and_ where there + is a different semantics of window handle and surface handle. + This is currently only true for Windows. */ + public void disposeSurfaceHandle() { + } + public AbstractGraphicsConfiguration getGraphicsConfiguration() { return config; } @@ -337,6 +344,12 @@ public abstract class Window implements NativeWindow private boolean autoDrawableMember = false; + /** If the implementation is capable of detecting a device change + return true and clear the status/reason of the change. */ + public boolean hasDeviceChanged() { + return false; + } + /** * If set to true, * certain action will be performed by the owning @@ -348,7 +361,7 @@ public abstract class Window implements NativeWindow protected void windowDestroyNotify() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyeNotify start"); + System.out.println("Window.windowDestroyeNotify start "+Thread.currentThread().getName()); } sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); @@ -358,13 +371,13 @@ public abstract class Window implements NativeWindow } if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyeNotify end"); + System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread().getName()); } } protected void windowDestroyed() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyed"); + System.out.println("Window.windowDestroyed "+Thread.currentThread().getName()); } invalidate(); } diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java new file mode 100644 index 000000000..4bcb2b2cb --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java @@ -0,0 +1,217 @@ +/* + * 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 com.sun.javafx.newt.awt; + +import com.sun.javafx.newt.Window; + +import java.awt.Canvas; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GraphicsConfiguration; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; +import com.sun.javafx.newt.impl.Debug; + +public class AWTCanvas extends Canvas { + private GraphicsDevice device; + private GraphicsConfiguration chosen; + private AWTGraphicsConfiguration awtConfig; + + private Capabilities capabilities; + + private boolean displayConfigChanged=false; + + public AWTCanvas(Capabilities capabilities) { + super(); + + if(null==capabilities) { + throw new NativeWindowException("Capabilities null"); + } + this.capabilities=capabilities; + } + + public AWTGraphicsConfiguration getAWTGraphicsConfiguration() { + return awtConfig; + } + + public boolean hasDeviceChanged() { + boolean res = displayConfigChanged; + displayConfigChanged=false; + return res; + } + + public void addNotify() { + super.addNotify(); + + GraphicsConfiguration gc = super.getGraphicsConfiguration(); + if(null!=gc) { + device = gc.getDevice(); + } + + /* + * Save the chosen capabilities for use in getGraphicsConfiguration(). + */ + awtConfig = chooseGraphicsConfiguration(capabilities, device); + if(Window.DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Created Config: "+awtConfig); + e.printStackTrace(); + } + if(null!=awtConfig) { + // update .. + chosen = awtConfig.getGraphicsConfiguration(); + } + if(null==awtConfig) { + throw new NativeWindowException("Error: AWTGraphicsConfiguration is null"); + } + } + + /** + * Overridden to choose a GraphicsConfiguration on a parent container's + * GraphicsDevice because both devices + */ + 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. + * - This canvas has been added to a component hierarchy and has + * an ancestor with a non-null GC, but the native peer has not + * yet been created. This means we can still choose the GC on + * all platforms since the peer hasn't been created. + */ + final GraphicsConfiguration gc = super.getGraphicsConfiguration(); + /* + * 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. + */ + if (gc != null && chosen != null && !chosen.equals(gc)) { + /* + * 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. + */ + AWTGraphicsConfiguration config = chooseGraphicsConfiguration((Capabilities)awtConfig.getRequestedCapabilities(), gc.getDevice()); + final GraphicsConfiguration compatible = (null!=config)?config.getGraphicsConfiguration():null; + if(Window.DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Call Stack: "+Thread.currentThread().getName()); + e.printStackTrace(); + System.err.println("!!! Created Config (n): HAVE GC "+chosen); + System.err.println("!!! Created Config (n): THIS GC "+gc); + System.err.println("!!! Created Config (n): Choosen GC "+compatible); + System.err.println("!!! Created Config (n): HAVE CF "+awtConfig); + System.err.println("!!! Created Config (n): Choosen CF "+config); + System.err.println("!!! Created Config (n): EQUALS CAPS "+config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())); + } + + if (compatible != null) { + /* + * Save the new GC for equals test above, and to return to + * any outside callers of this method. + */ + chosen = compatible; + if( !config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) { + displayConfigChanged=true; + } + awtConfig = config; + } + } + + /* + * If a compatible GC was not found in the block above, this will + * 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) { + /* + * The GC is null, which means we have no native peer, and are not + * part of a (realized) component hierarchy. So we return the + * desired visual that was selected in the constructor (possibly + * null). + */ + return chosen; + } + + /* + * Otherwise we have not explicitly selected a GC in the constructor, so + * just return what Canvas would have. + */ + return gc; + } + + private static AWTGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + GraphicsDevice device) { + AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device); + AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capabilities, + null, + aScreen); + if (config == null) { + throw new NativeWindowException("Error: Couldn't fetch AWTGraphicsConfiguration"); + } + + return config; + } + +} diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java index f6f4a6fe8..099125630 100644 --- a/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java @@ -46,5 +46,9 @@ public class AWTDisplay extends Display { aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default } + protected void setAWTGraphicsDevice(AWTGraphicsDevice d) { + aDevice = d; + } + protected void closeNative() { } } diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java index 93e57d72f..73436c3be 100644 --- a/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java @@ -45,6 +45,10 @@ public class AWTScreen extends Screen { aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); } + protected void setAWTGraphicsScreen(AWTGraphicsScreen s) { + aScreen = s; + } + protected void closeNative() { } } diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java index cb8c56d55..35413f132 100644 --- a/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java @@ -62,12 +62,11 @@ public class AWTWindow extends Window { } private Frame frame; - private Canvas canvas; + private AWTCanvas canvas; private LinkedList/*<AWTEventWrapper>*/ events = new LinkedList(); private boolean gotDisplaySize; private int displayWidth; private int displayHeight; - private volatile boolean awtCreated=false; public void setTitle(String title) { super.setTitle(title); @@ -76,47 +75,26 @@ public class AWTWindow extends Window { } } - Object syncObj = new Object(); - - protected void createNative(Capabilities caps) { - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); - if (config == null) { - throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); - } + protected void createNative(final Capabilities caps) { runOnEDT(new Runnable() { public void run() { - synchronized (syncObj) { - frame = new Frame(getTitle()); - frame.setUndecorated(isUndecorated()); - frame.setLayout(new BorderLayout()); - canvas = new Canvas( ((AWTGraphicsConfiguration) config).getGraphicsConfiguration() ); - Listener listener = new Listener(); - canvas.addMouseListener(listener); - canvas.addMouseMotionListener(listener); - canvas.addKeyListener(listener); - canvas.addComponentListener(listener); - frame.add(canvas, BorderLayout.CENTER); - frame.setSize(width, height); - frame.setLocation(x, y); - frame.addComponentListener(new MoveListener()); - frame.addWindowListener(new WindowEventListener()); - awtCreated=true; - syncObj.notifyAll(); - } + frame = new Frame(getTitle()); + frame.setUndecorated(isUndecorated()); + frame.setLayout(new BorderLayout()); + canvas = new AWTCanvas(caps); + Listener listener = new Listener(); + canvas.addMouseListener(listener); + canvas.addMouseMotionListener(listener); + canvas.addKeyListener(listener); + canvas.addComponentListener(listener); + frame.add(canvas, BorderLayout.CENTER); + frame.setSize(width, height); + frame.setLocation(x, y); + frame.addComponentListener(new MoveListener()); + frame.addWindowListener(new WindowEventListener()); } }); - - // make sure we are finished .. - while(!awtCreated) { - synchronized (syncObj) { - if(!awtCreated) { - try { - syncObj.wait(); - } catch (InterruptedException e) {} - } - } - } } protected void closeNative() { @@ -128,6 +106,20 @@ public class AWTWindow extends Window { }); } + public boolean hasDeviceChanged() { + boolean res = canvas.hasDeviceChanged(); + if(res) { + config = canvas.getAWTGraphicsConfiguration(); + if (config == null) { + throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this); + } + // propagate new info .. + ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)config.getScreen()); + ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)config.getScreen().getDevice()); + } + return res; + } + public int getDisplayWidth() { getDisplaySize(); return displayWidth; @@ -154,6 +146,16 @@ public class AWTWindow extends Window { frame.setVisible(visible); } }); + + config = canvas.getAWTGraphicsConfiguration(); + + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + // propagate new info .. + ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)config.getScreen()); + ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)config.getScreen().getDevice()); } public void setSize(final int width, final int height) { @@ -238,7 +240,7 @@ public class AWTWindow extends Window { default: throw new NativeWindowException("Unknown event type " + w.getType()); } - if(DEBUG_MOUSE_EVENT) { + if(Window.DEBUG_MOUSE_EVENT) { System.out.println("dispatchMessages: in event:"+w.getEvent()); } } diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java index cd784c858..6dfd57441 100644 --- a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java @@ -153,7 +153,7 @@ public class GLWindow extends Window implements GLAutoDrawable { protected void dispose(boolean regenerate) { if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.destroy("+regenerate+") 1: "+this); + Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", 1: "+this); e1.printStackTrace(); } @@ -166,22 +166,39 @@ public class GLWindow extends Window implements GLAutoDrawable { drawable.setRealized(false); } + if(null!=window) { + window.disposeSurfaceHandle(); + } + if(regenerate) { + if(null==window) { + throw new GLException("GLWindow.dispose(true): null window"); + } + + // recreate GLDrawable, to reflect the new graphics configurations + NativeWindow nw; + if (window.getWrappedWindow() != null) { + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; + } + drawable = factory.createGLDrawable(nw); drawable.setRealized(true); if(getSurfaceHandle()==0) { throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this); } context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.dispose("+regenerate+") fin: "+this); + System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", fin: "+this); } } public synchronized void destroy() { if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.destroy 1: "+this); + Exception e1 = new Exception("GLWindow.destroy "+Thread.currentThread().getName()+", 1: "+this); e1.printStackTrace(); } @@ -200,7 +217,7 @@ public class GLWindow extends Window implements GLAutoDrawable { } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.destroy fin: "+this); + System.out.println("GLWindow.destroy "+Thread.currentThread().getName()+", fin: "+this); } drawable = null; @@ -288,9 +305,11 @@ public class GLWindow extends Window implements GLAutoDrawable { public void setVisible(boolean visible) { window.setVisible(visible); if (visible && context == null) { - NativeWindow nw = window; + NativeWindow nw; if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), nw.getGraphicsConfiguration()); + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; } GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); @@ -300,6 +319,7 @@ public class GLWindow extends Window implements GLAutoDrawable { throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this); } context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. } } @@ -449,6 +469,9 @@ public class GLWindow extends Window implements GLAutoDrawable { public void display() { if(getSurfaceHandle()!=0) { pumpMessages(); + if(window.hasDeviceChanged()) { + dispose(true); + } if (sendDestroy) { destroy(); sendDestroy=false; diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java index abb26a009..ddaf973c5 100755 --- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java @@ -40,6 +40,7 @@ import com.sun.javafx.newt.impl.*; public class WindowsWindow extends Window { + private long hmon; private long hdc; private long windowHandleClose; @@ -58,10 +59,41 @@ public class WindowsWindow extends Window { public long getSurfaceHandle() { if (hdc == 0) { hdc = GetDC(windowHandle); + hmon = MonitorFromWindow(windowHandle); + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window new surface handle "+Thread.currentThread().getName()+ + ",HDC 0x"+Long.toHexString(hdc)+", HMON 0x"+Long.toHexString(hmon)); + e.printStackTrace(); + } } return hdc; } + public boolean hasDeviceChanged() { + long _hmon = MonitorFromWindow(windowHandle); + if (hmon != _hmon) { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window Device Changed "+Thread.currentThread().getName()+ + ", HMON 0x"+Long.toHexString(hmon)+" -> 0x"+Long.toHexString(_hmon)); + e.printStackTrace(); + } + hmon = _hmon; + return true; + } + return false; + } + + public void disposeSurfaceHandle() { + if (hdc != 0) { + ReleaseDC(windowHandle, hdc); + hdc=0; + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window surface handle disposed "+Thread.currentThread().getName()); + e.printStackTrace(); + } + } + } + protected void createNative(Capabilities caps) { long wndClass = getWindowClass(); config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); @@ -188,6 +220,7 @@ public class WindowsWindow extends Window { private native void DestroyWindow(long windowHandle); private native long GetDC(long windowHandle); private native void ReleaseDC(long windowHandle, long hdc); + private native long MonitorFromWindow(long windowHandle); private native void setVisible0(long windowHandle, boolean visible); private static native void DispatchMessages(long windowHandle, int eventMask); private native void setSize0(long windowHandle, int width, int height); |