diff options
author | Sven Gothel <[email protected]> | 2010-05-05 15:30:33 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-05-05 15:30:33 +0200 |
commit | 599bf2dea34e82e32a7b443900a0c24c92b96b80 (patch) | |
tree | 083be99b7dbc800c7369b3b2559601d492252e6a /src | |
parent | ccc30b050b98d3ac19779e1dc2d0fcee68331863 (diff) |
Newt: Add generic NativeWindow parenting, inclusive using an AWT Component as a parent
Diffstat (limited to 'src')
6 files changed, 629 insertions, 50 deletions
diff --git a/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java new file mode 100755 index 000000000..fb25ae399 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/jogl/demos/gl2/gears/TestGearsNewtAWTWrapper.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.test.junit.jogl.demos.gl2.gears; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.util.Animator; + +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.AfterClass; +import org.junit.After; +import org.junit.Test; + +public class TestGearsNewtAWTWrapper { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getDefault(); + Assert.assertNotNull(glp); + width = 512; + height = 512; + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps) throws InterruptedException { + Display nDisplay = NewtFactory.createDisplay(NativeWindowFactory.TYPE_AWT, null); // local display + Screen nScreen = NewtFactory.createScreen(NativeWindowFactory.TYPE_AWT, nDisplay, 0); // screen 0 + Window nWindow = NewtFactory.createWindow(NativeWindowFactory.TYPE_AWT, nScreen, caps); + + GLWindow glWindow = GLWindow.create(nWindow); + Assert.assertNotNull(glWindow); + glWindow.setTitle("Gears NewtAWTWrapper Test"); + + glWindow.addGLEventListener(new Gears()); + + Animator animator = new Animator(glWindow); + QuitAdapter quitAdapter = new QuitAdapter(); + + glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); + glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); + + glWindow.setSize(width, height); + glWindow.setVisible(true); + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + glWindow.destroy(true); + } + + @Test + public void test01() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + runTestGL(caps); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + try { + duration = Integer.parseInt(args[i]); + } catch (Exception ex) { ex.printStackTrace(); } + } + } + org.junit.runner.JUnitCore.main(TestGearsNewtAWTWrapper.class.getName()); + } +} diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01AWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01AWT.java new file mode 100755 index 000000000..4c21684d3 --- /dev/null +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01AWT.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.test.junit.newt; + +import java.lang.reflect.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Test; + +import java.awt.Button; +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Component; +import java.awt.Frame; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; + +import com.jogamp.newt.*; +import com.jogamp.newt.event.*; +import com.jogamp.newt.opengl.*; + +import java.io.IOException; + +import com.jogamp.test.junit.util.*; +import com.jogamp.test.junit.jogl.demos.es1.RedSquare; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; + +public class TestParenting01AWT { + static int width, height; + static long durationPerTest = 500; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + } + + static void destroyWindow(Display display, Screen screen, Window window, GLWindow glWindow) { + if(null!=glWindow) { + glWindow.destroy(); + } + if(null!=window) { + window.destroy(); + } + if(null!=screen) { + screen.destroy(); + } + if(null!=display) { + display.destroy(); + } + } + + @Test + public void testWindowParenting01NewtChildOnAWTParentLayouted() throws InterruptedException { + runNewtChildOnAWTParent(true); + } + + @Test + public void testWindowParenting02NewtChildOnAWTParentDirect() throws InterruptedException { + runNewtChildOnAWTParent(false); + } + + public void runNewtChildOnAWTParent(boolean useLayout) throws InterruptedException { + Frame frame = new Frame("AWT Parent Frame"); + Assert.assertNotNull(frame); + Component overlayedAWTComponent = null; + + if(useLayout) { + overlayedAWTComponent = new Canvas(); + + frame.setLayout(new BorderLayout()); + frame.add(new Button("North"), BorderLayout.NORTH); + frame.add(new Button("South"), BorderLayout.SOUTH); + frame.add(new Button("East"), BorderLayout.EAST); + frame.add(new Button("West"), BorderLayout.WEST); + frame.add(overlayedAWTComponent, BorderLayout.CENTER); + + } else { + overlayedAWTComponent = frame; + } + + Assert.assertNotNull(overlayedAWTComponent); + frame.setSize(width, height); + frame.setVisible(true); // should have native peers after this! + + GLCapabilities caps = new GLCapabilities(null); + Assert.assertNotNull(caps); + Display display = NewtFactory.createDisplay(null); // local display + Assert.assertNotNull(display); + System.out.println("Display: "+display); + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + Assert.assertNotNull(screen); + + final NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + + Window window2 = NewtFactory.createWindow(overlayedAWTComponent, screen, caps); + Assert.assertNotNull(window2); + + GLWindow glWindow2 = GLWindow.create(window2); + Assert.assertNotNull(glWindow2); + + glWindow2.setSize(width, height); + Assert.assertTrue(false==glWindow2.isVisible()); + Assert.assertTrue(width==glWindow2.getWidth()); + Assert.assertTrue(height==glWindow2.getHeight()); + + glWindow2.setTitle("NEWT - CHILD"); + glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); + glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent e) { + eventFifo.put(e); + } + })); + + GLEventListener demo2 = new Gears(); + setDemoFields(demo2, window2, glWindow2, false); + glWindow2.addGLEventListener(demo2); + + glWindow2.setVisible(true); + glWindow2.display(); + + long duration = durationPerTest; + long step = 20; + NEWTEvent event; + boolean shouldQuit = false; + + while (duration>0 && !shouldQuit) { + glWindow2.display(); + Thread.sleep(step); + duration -= step; + + while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + Window source = (Window) event.getSource(); + if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) { + shouldQuit = true; + } else if(event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent) event; + switch(keyEvent.getKeyChar()) { + case 'q': + shouldQuit = true; + break; + case 'f': + source.setFullscreen(!source.isFullscreen()); + break; + } + } + } + } + destroyWindow(null, null, window2, glWindow2); + frame.dispose(); + } + + public static void setDemoFields(GLEventListener demo, Window window, GLWindow glWindow, boolean debug) { + Assert.assertNotNull(demo); + Assert.assertNotNull(window); + if(debug) { + MiscUtils.setFieldIfExists(demo, "glDebug", true); + MiscUtils.setFieldIfExists(demo, "glTrace", true); + } + if(!MiscUtils.setFieldIfExists(demo, "window", window)) { + MiscUtils.setFieldIfExists(demo, "glWindow", glWindow); + } + } + + public static void main(String args[]) throws IOException { + durationPerTest = 5000; + String tstname = TestParenting01AWT.class.getName(); + org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(new String[] { + tstname, + "filtertrace=true", + "haltOnError=false", + "haltOnFailure=false", + "showoutput=true", + "outputtoformatters=true", + "logfailedtests=true", + "logtestlistenerevents=true", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter", + "formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,TEST-"+tstname+".xml" } ); + } + +} diff --git a/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java index 128c4358d..9528009ea 100755 --- a/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestParenting01NEWT.java @@ -68,26 +68,18 @@ public class TestParenting01NEWT { height = 480; } - static Window createWindow(NativeWindow parent, Screen screen, Capabilities caps, int width, int height, boolean onscreen, boolean undecorated) { + static Window createWindow(NativeWindow parent, Screen screen, Capabilities caps, int width, int height) { Assert.assertNotNull(caps); - caps.setOnscreen(onscreen); - // System.out.println("Requested: "+caps); - // // Create native windowing resources .. X11/Win/OSX // Window window; - if(null==parent) { - window = NewtFactory.createWindow(screen, caps, onscreen && undecorated); - } else { - window = NewtFactory.createWindow(parent.getWindowHandle(), screen, caps, onscreen && undecorated); - } + window = ( null == parent ) ? NewtFactory.createWindow(screen, caps) : NewtFactory.createWindow(parent, screen, caps) ; Assert.assertNotNull(window); window.setSize(width, height); Assert.assertTrue(false==window.isVisible()); Assert.assertTrue(width==window.getWidth()); Assert.assertTrue(height==window.getHeight()); - System.out.println("Created: "+window); // // Create native OpenGL resources .. XGL/WGL/CGL .. @@ -98,7 +90,7 @@ public class TestParenting01NEWT { Assert.assertTrue(caps.getGreenBits()>5); Assert.assertTrue(caps.getBlueBits()>5); Assert.assertTrue(caps.getRedBits()>5); - Assert.assertTrue(caps.isOnscreen()==onscreen); + Assert.assertTrue(caps.isOnscreen()==true); return window; } @@ -130,28 +122,34 @@ public class TestParenting01NEWT { int x = 1; int y = 1; - NEWTEventFiFo eventFifo = new NEWTEventFiFo(); + final NEWTEventFiFo eventFifo = new NEWTEventFiFo(); - Window window1 = createWindow( null, screen, caps, width, height, true /* onscreen */, false /* undecorated */); + Window window1 = createWindow( null, screen, caps, width, height ); Assert.assertNotNull(window1); - window1.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - PARENT"); - window1.setPosition(x,y); - window1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); GLWindow glWindow1 = GLWindow.create(window1); Assert.assertNotNull(glWindow1); - - Window window2 = createWindow(window1, screen, caps, width/2, height/2, true /* onscreen */, false /* undecorated */); + Assert.assertTrue(width==glWindow1.getWidth()); + Assert.assertTrue(height==glWindow1.getHeight()); + glWindow1.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - PARENT"); + glWindow1.setPosition(x,y); + glWindow1.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); + glWindow1.addWindowListener(new TraceWindowAdapter()); + + Window window2 = createWindow(window1, screen, caps, width/2, height/2); Assert.assertNotNull(window2); - window2.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - CHILD"); - System.out.println("Window1: "+window1); - Assert.assertTrue(width==window1.getWidth()); - Assert.assertTrue(height==window1.getHeight()); - window2.setPosition(window1.getWidth()/2, window1.getHeight()/2); - window2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); - // window2.addMouseListener(new TraceMouseAdapter()); - window2.requestFocus(); GLWindow glWindow2 = GLWindow.create(window2); Assert.assertNotNull(glWindow2); + Assert.assertTrue(width/2==glWindow2.getWidth()); + Assert.assertTrue(height/2==glWindow2.getHeight()); + glWindow2.setTitle("testWindowParenting01NewtOnNewtParentChildDraw - CHILD"); + glWindow2.setPosition(glWindow1.getWidth()/2, glWindow1.getHeight()/2); + glWindow2.addKeyListener(new TraceKeyAdapter(new KeyAction(eventFifo))); + glWindow2.addWindowListener(new TraceWindowAdapter(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent e) { + eventFifo.put(e); + } + })); + // glWindow2.addMouseListener(new TraceMouseAdapter()); GLEventListener demo1 = new RedSquare(); setDemoFields(demo1, window1, glWindow1, false); @@ -161,8 +159,8 @@ public class TestParenting01NEWT { setDemoFields(demo2, window2, glWindow2, false); glWindow2.addGLEventListener(demo2); - window2.setVisible(true); - window1.setVisible(true); + glWindow2.setVisible(true); + glWindow1.setVisible(true); glWindow2.setVisible(true); glWindow1.setVisible(true); @@ -170,34 +168,37 @@ public class TestParenting01NEWT { glWindow2.display(); glWindow1.display(); + boolean shouldQuit = false; long duration = durationPerTest; long step = 20; - KeyEvent keyEvent; - boolean shouldQuit = false; + NEWTEvent event; while (duration>0 && !shouldQuit) { - while( null != ( keyEvent = (KeyEvent) eventFifo.get() ) ) { - Window source = (Window) keyEvent.getSource(); - switch(keyEvent.getKeyChar()) { - case 'q': - System.out.println(keyEvent); - shouldQuit = true; - break; - case 'f': - System.out.println(keyEvent); - source.setFullscreen(!source.isFullscreen()); - break; - } - } - glWindow1.display(); glWindow2.display(); - Thread.sleep(step); // 1000 ms + Thread.sleep(step); duration -= step; x += 1; y += 1; - window1.setPosition(x,y); - window2.setPosition(window1.getWidth()/2,window1.getHeight()/2-y); + glWindow1.setPosition(x,y); + glWindow2.setPosition(glWindow1.getWidth()/2,glWindow1.getHeight()/2-y); + + while( null != ( event = (NEWTEvent) eventFifo.get() ) ) { + Window source = (Window) event.getSource(); + if(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY == event.getEventType()) { + shouldQuit = true; + } else if(event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent) event; + switch(keyEvent.getKeyChar()) { + case 'q': + shouldQuit = true; + break; + case 'f': + source.setFullscreen(!source.isFullscreen()); + break; + } + } + } } destroyWindow(null, null, window2, glWindow2); destroyWindow(display, screen, window1, glWindow1); diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 2d5c10c52..531d686b2 100755 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -33,10 +33,13 @@ package com.jogamp.newt; +import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.*; import java.util.ArrayList; import java.util.Iterator; import com.jogamp.common.jvm.JVMUtil; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; public abstract class NewtFactory { // Work-around for initialization order problems on Mac OS X @@ -100,18 +103,87 @@ public abstract class NewtFactory { } /** - * Create a Window entity, incl native creation + * Create a top level Window entity, incl native creation */ public static Window createWindow(Screen screen, Capabilities caps) { return Window.create(NativeWindowFactory.getNativeWindowType(true), 0, screen, caps, false); } + /** + * Create a top level Window entity, incl native creation + */ public static Window createWindow(Screen screen, Capabilities caps, boolean undecorated) { return Window.create(NativeWindowFactory.getNativeWindowType(true), 0, screen, caps, undecorated); } - public static Window createWindow(long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), parentWindowHandle, screen, caps, undecorated); + /** + * Create a child Window entity attached to the given parent, incl native creation<br> + * <p> + * In case <code>parentWindowObject</code> is a {@link javax.media.nativewindow.NativeWindow},<br> + * we create a child {@link com.jogamp.newt.Window}, + * utilizing {@link com.jogamp.newt.NewtFactory#createWindow(long, com.jogamp.newt.Screen, com.jogamp.newt.Capabilities)}, + * passing the parent's native window handle retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.<br></p> + * <p> + * In case <code>parentWindowObject</code> is even a {@link com.jogamp.newt.Window}, the following applies:<br> + * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for e.g. layout<br>, + * you have to add an appropriate {@link com.jogamp.newt.event.WindowListener} for this use case.<br> + * However, {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY} is propagated to the child window, so it will be closed properly.<br> + * In case <code>parentWindowObject</code> is a different {@javax.media.nativewindow.NativeWindow} implementation,<br> + * you have to handle all events appropriatly.<br></p> + * <p> + * In case <code>parentWindowObject</code> is a {@link java.awt.Component},<br> + * we utilize the {@link com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Screen, com.jogamp.newt.Capabilities)} + * factory method.<br> + * The factory adds a {@link com.jogamp.newt.event.WindowListener} to propagate {@link com.jogamp.newt.event.WindowEvent}'s so + * your NEWT Window integrates into the AWT layout.<br></p> + * + * @param parentWindowObject either a NativeWindow or java.awt.Component + * + * @see com.jogamp.newt.NewtFactory#createWindow(long, com.jogamp.newt.Screen, com.jogamp.newt.Capabilities) + * @see com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Screen, com.jogamp.newt.Capabilities) + */ + public static Window createWindow(Object parentWindowObject, Screen screen, Capabilities caps) { + if(null==parentWindowObject) { + throw new RuntimeException("Null parentWindowObject"); + } + if(parentWindowObject instanceof NativeWindow) { + NativeWindow nativeParentWindow = (NativeWindow) parentWindowObject; + nativeParentWindow.lockSurface(); + long parentWindowHandle = nativeParentWindow.getWindowHandle(); + nativeParentWindow.unlockSurface(); + final Window win = createWindow(parentWindowHandle, screen, caps); + if ( nativeParentWindow instanceof Window) { + final Window f_nativeParentWindow = (Window) nativeParentWindow ; + f_nativeParentWindow.addWindowListener(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent e) { + win.sendEvent(e); + } + }); + } + return win; + } else { + if(ReflectionUtil.instanceOf(parentWindowObject, "java.awt.Component")) { + if(ReflectionUtil.isClassAvailable("com.jogamp.newt.impl.awt.AWTNewtFactory")) { + return (Window) ReflectionUtil.callStaticMethod("com.jogamp.newt.impl.awt.AWTNewtFactory", + "createNativeChildWindow", + new Class[] { Object.class, Screen.class, Capabilities.class }, + new Object[] { parentWindowObject, screen, caps } ); + } + } + } + throw new RuntimeException("No NEWT child Window factory method for parent object: "+parentWindowObject); + } + + /** + * Create a child Window entity attached to the given parent, incl native creation<br> + * + * @param parentWindowObject the native parent window handle + */ + public static Window createWindow(long parentWindowHandle, Screen screen, Capabilities caps) { + if(0==parentWindowHandle) { + throw new RuntimeException("Null parentWindowHandle"); + } + return Window.create(NativeWindowFactory.getNativeWindowType(true), parentWindowHandle, screen, caps, true); } /** diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java new file mode 100644 index 000000000..49d9bf0f2 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ +package com.jogamp.newt.event.awt; + +/** + * 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 +{ + public AWTParentWindowAdapter(com.jogamp.newt.Window downstream) { + super(downstream); + } + + public void componentResized(java.awt.event.ComponentEvent e) { + // need to really resize the NEWT child window + java.awt.Component comp = e.getComponent(); + newtWindow.setSize(comp.getWidth(), comp.getHeight()); + } + + public void componentMoved(java.awt.event.ComponentEvent e) { + // no propagation to NEWT child window + } + + public void windowActivated(java.awt.event.WindowEvent e) { + // no propagation to NEWT child window ?? FIXME: Maybe yes in case of a 100% Opaque one ? + } + + public void windowDeactivated(java.awt.event.WindowEvent e) { + // no propagation to NEWT child window ?? FIXME: Maybe yes in case of a 100% Opaque one ? + } +} + diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java new file mode 100644 index 000000000..f3296d9d5 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010 Sven Gothel. 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 Sven Gothel 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 + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.newt.impl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.Component; +import java.awt.Canvas; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.NewtFactory; + +public class AWTNewtFactory { + + /** + * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},<br> + * using a configuration agnostic dummy {@link javax.media.nativewindow.DefaultGraphicsConfiguration}.<br> + * <p> + * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.<br></p> + * <p> + * Purpose of this wrapping is to access the AWT window handle,<br> + * not to actually render into it.<br> + * Hence the dummy configuration only.</p> + * + * @param awtCompObject must be of type java.awt.Component + */ + public static NativeWindow getNativeWindow(Object awtCompObject) { + if(null==awtCompObject) { + throw new NativeWindowException("Null AWT Component"); + } + if( ! (awtCompObject instanceof java.awt.Component) ) { + throw new NativeWindowException("AWT Component not a java.awt.Component"); + } + java.awt.Component awtComp = (java.awt.Component) awtCompObject; + DefaultGraphicsDevice dummyDevice = new DefaultGraphicsDevice("AWTNewtBridge"); + DefaultGraphicsScreen dummyScreen = new DefaultGraphicsScreen(dummyDevice, 0); + Capabilities dummyCaps = new Capabilities(); + DefaultGraphicsConfiguration dummyConfig = new DefaultGraphicsConfiguration(dummyScreen, dummyCaps, dummyCaps); + NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, dummyConfig); + return awtNative; + } + + /** + * Creates a native NEWT child window to a AWT parent window.<br> + * <p> + * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, + * utilizing {@link #getNativeWindow(java.awt.Component)}.<br> + * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.<br></p> + * <p> + * Second we create a child {@link com.jogamp.newt.Window}, utilizing {@link com.jogamp.newt.NewtFactory#createWindow(long, com.jogamp.newt.Screen, com.jogamp.newt.Capabilities)}, passing the AWT parent's native window handle retrieved via {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow#getWindowHandle()}.<br></p> + * <p> + * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.<br> + * The adapter passes window related events to our new child window, look at the implementation<br></p> + * + * @param awtParentObject must be of type java.awt.Component + */ + public static Window createNativeChildWindow(Object awtParentObject, Screen newtScreen, Capabilities newtCaps) { + NativeWindow parent = getNativeWindow(awtParentObject); // also checks java.awt.Component type + java.awt.Component awtParent = (java.awt.Component) awtParentObject; + if(null==parent) { + throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); + } + parent.lockSurface(); + long windowHandle = parent.getWindowHandle(); + parent.unlockSurface(); + if(0==windowHandle) { + throw new NativeWindowException("Null window handle: "+parent); + } + Window window = NewtFactory.createWindow(windowHandle, newtScreen, newtCaps); + new AWTParentWindowAdapter(window).addTo(awtParent); + return window; + } +} + |