Jogamp
cc92c49630fe0c637c126b869138f3d555ebe470
[jogl.git] / src / newt / classes / jogamp / newt / driver / awt / WindowDriver.java
1 /*
2  * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * Copyright (c) 2010 JogAmp Community. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * - Redistribution of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * - Redistribution in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32  *
33  */
34
35 package jogamp.newt.driver.awt;
36
37 import java.awt.BorderLayout;
38 import java.awt.Container;
39 import java.awt.Dimension;
40 import java.awt.Frame;
41 import java.awt.Insets;
42
43 import javax.media.nativewindow.NativeSurface;
44 import javax.media.nativewindow.NativeWindow;
45 import javax.media.nativewindow.NativeWindowException;
46 import javax.media.nativewindow.util.Point;
47
48 import jogamp.nativewindow.awt.AWTMisc;
49 import jogamp.newt.WindowImpl;
50
51 import com.jogamp.common.os.Platform;
52 import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
53 import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
54 import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
55 import com.jogamp.newt.event.WindowEvent;
56 import com.jogamp.newt.event.WindowUpdateEvent;
57 import com.jogamp.newt.event.awt.AWTKeyAdapter;
58 import com.jogamp.newt.event.awt.AWTMouseAdapter;
59 import com.jogamp.newt.event.awt.AWTWindowAdapter;
60
61 /** An implementation of the Newt Window class built using the
62     AWT. This is provided for convenience of porting to platforms
63     supporting Java SE. */
64
65 public class WindowDriver extends WindowImpl {
66
67     public WindowDriver() {
68         this(null);
69     }
70
71     public static Class<?>[] getCustomConstructorArgumentTypes() {
72         return new Class<?>[] { Container.class } ;
73     }
74
75     public WindowDriver(Container container) {
76         super();
77         this.awtContainer = container;
78         if(container instanceof Frame) {
79             awtFrame = (Frame) container;
80         }
81     }
82
83     private boolean owningFrame;
84     private Container awtContainer = null;
85     /** same instance as container, just for impl. convenience */
86     private Frame awtFrame = null;
87     private AWTCanvas awtCanvas;
88
89     @Override
90     protected void requestFocusImpl(boolean reparented) {
91         awtContainer.requestFocus();
92     }
93
94     @Override
95     protected void setTitleImpl(final String title) {
96         if (awtFrame != null) {
97             awtFrame.setTitle(title);
98         }
99     }
100
101     @Override
102     protected final int getPixelScaleX() {
103         final AWTCanvas _awtCanvas = awtCanvas;
104         return null != _awtCanvas ? _awtCanvas.getPixelScale() : 1;
105     }
106
107     @Override
108     protected final int getPixelScaleY() {
109         return getPixelScaleX();
110     }
111
112     @Override
113     protected void createNativeImpl() {
114         if(0!=getParentWindowHandle()) {
115             throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
116         }
117
118         if(null==awtContainer) {
119             awtFrame = new Frame();
120             awtContainer = awtFrame;
121             owningFrame=true;
122         } else {
123             owningFrame=false;
124             defineSize(awtContainer.getWidth(), awtContainer.getHeight());
125             definePosition(awtContainer.getX(), awtContainer.getY());
126         }
127         if(null!=awtFrame) {
128             awtFrame.setTitle(getTitle());
129         }
130         awtContainer.setLayout(new BorderLayout());
131
132         if( null == awtCanvas ) {
133             awtCanvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser);
134
135             // canvas.addComponentListener(listener);
136             awtContainer.add(awtCanvas, BorderLayout.CENTER);
137
138             // via EDT ..
139             new AWTMouseAdapter(this).addTo(awtCanvas); // fwd all AWT Mouse events to here
140             new AWTKeyAdapter(this).addTo(awtCanvas); // fwd all AWT Key events to here
141
142             // direct w/o EDT
143             new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here
144         }
145
146         reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
147         // throws exception if failed ..
148
149         final NativeWindow nw = awtCanvas.getNativeWindow();
150         if( null != nw ) {
151             setGraphicsConfiguration( awtCanvas.getAWTGraphicsConfiguration() );
152             setWindowHandle( nw.getWindowHandle() );
153         }
154     }
155
156     @Override
157     protected void closeNativeImpl() {
158         setWindowHandle(0);
159         if(null!=awtContainer) {
160             awtContainer.setVisible(false);
161             awtContainer.remove(awtCanvas);
162             awtContainer.setEnabled(false);
163             awtCanvas.setEnabled(false);
164         }
165         if(owningFrame && null!=awtFrame) {
166             awtFrame.dispose();
167             owningFrame=false;
168         }
169         awtCanvas = null;
170         awtFrame = null;
171         awtContainer = null;
172     }
173
174     @Override
175     public boolean hasDeviceChanged() {
176         boolean res = awtCanvas.hasDeviceChanged();
177         if(res) {
178             final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
179             if (null == cfg) {
180                 throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
181             }
182             setGraphicsConfiguration(cfg);
183
184             // propagate new info ..
185             ((ScreenDriver)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen());
186             ((DisplayDriver)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice());
187
188             ((ScreenDriver)getScreen()).updateVirtualScreenOriginAndSize();
189         }
190         return res;
191     }
192
193     @Override
194     protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) {
195         final Insets contInsets = awtContainer.getInsets();
196         insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
197     }
198
199     private void setCanvasSizeImpl(int width, int height) {
200         final Dimension szClient = new Dimension(width, height);
201         final java.awt.Window awtWindow = AWTMisc.getWindow(awtCanvas);
202         final Container c= null != awtWindow ? awtWindow : awtContainer;
203         awtCanvas.setMinimumSize(szClient);
204         awtCanvas.setPreferredSize(szClient);
205         if(DEBUG_IMPLEMENTATION) {
206             final Insets insets = c.getInsets();
207             final Dimension szContainer = new Dimension(width + insets.left + insets.right,
208                                                         height + insets.top + insets.bottom);
209             System.err.println(getThreadName()+": AWTWindow setCanvasSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
210         }
211         awtCanvas.setSize(szClient);
212         awtCanvas.invalidate();
213         if(null != awtWindow) {
214             awtWindow.pack();
215         } else {
216             awtContainer.validate();
217         }
218     }
219     private void setFrameSizeImpl(int width, int height) {
220         final Insets insets = awtContainer.getInsets();
221         final Dimension szContainer = new Dimension(width + insets.left + insets.right,
222                                                     height + insets.top + insets.bottom);
223         if(DEBUG_IMPLEMENTATION) {
224             final Dimension szClient = new Dimension(width, height);
225             System.err.println(getThreadName()+": AWTWindow setFrameSize: szClient "+szClient+", szCont "+szContainer+", insets "+insets);
226         }
227         awtContainer.setSize(szContainer);
228         awtCanvas.invalidate();
229         awtContainer.validate();
230     }
231
232     @Override
233     protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) {
234         if(DEBUG_IMPLEMENTATION) {
235             System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
236                                getReconfigureFlagsAsString(null, flags));
237         }
238         if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=awtFrame) {
239             if(!awtContainer.isDisplayable()) {
240                 awtFrame.setUndecorated(isUndecorated());
241             } else {
242                 if(DEBUG_IMPLEMENTATION) {
243                     System.err.println(getThreadName()+": AWTWindow can't undecorate already created frame");
244                 }
245             }
246         }
247
248         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
249             if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
250                 setCanvasSizeImpl(width, height);
251                 awtContainer.setVisible( true );
252             } else {
253                 awtContainer.setVisible( false );
254             }
255         } else if( awtCanvas.getWidth() != width || awtCanvas.getHeight() != height ) {
256             if( Platform.OSType.MACOS == Platform.getOSType() && awtCanvas.isOffscreenLayerSurfaceEnabled() ) {
257                 setFrameSizeImpl(width, height);
258             } else {
259                 setCanvasSizeImpl(width, height);
260             }
261         }
262         defineSize(width, height); // we are on AWT-EDT .. change values immediately
263
264         if( awtContainer.getX() != x || awtContainer.getY() != y ) {
265             awtContainer.setLocation(x, y);
266         }
267
268         if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
269             if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
270                 if( !hasDeviceChanged() ) {
271                     // oops ??
272                     final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
273                     if(null == cfg) {
274                         throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this);
275                     }
276                     setGraphicsConfiguration(cfg);
277                 }
278             }
279             visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
280         }
281
282         return true;
283     }
284
285     @Override
286     protected Point getLocationOnScreenImpl(int x, int y) {
287         java.awt.Point ap = awtCanvas.getLocationOnScreen();
288         ap.translate(x, y);
289         return new Point((int)(ap.getX()+0.5),(int)(ap.getY()+0.5));
290     }
291
292     @Override
293     public NativeSurface getWrappedSurface() {
294         return ( null != awtCanvas ) ? awtCanvas.getNativeWindow() : null;
295     }
296
297     class LocalWindowListener implements com.jogamp.newt.event.WindowListener {
298         @Override
299         public void windowMoved(com.jogamp.newt.event.WindowEvent e) {
300             if(null!=awtContainer) {
301                 WindowDriver.this.positionChanged(false, awtContainer.getX(), awtContainer.getY());
302             }
303         }
304         @Override
305         public void windowResized(com.jogamp.newt.event.WindowEvent e) {
306             if(null!=awtCanvas) {
307                 if(DEBUG_IMPLEMENTATION) {
308                     System.err.println("Window Resized: "+awtCanvas);
309                 }
310                 WindowDriver.this.sizeChanged(false, awtCanvas.getWidth(), awtCanvas.getHeight(), true);
311                 WindowDriver.this.windowRepaint(false, 0, 0, getSurfaceWidth(), getSurfaceHeight());
312             }
313         }
314         @Override
315         public void windowDestroyNotify(WindowEvent e) {
316             WindowDriver.this.windowDestroyNotify(false);
317         }
318         @Override
319         public void windowDestroyed(WindowEvent e) {
320             // Not fwd by AWTWindowAdapter, synthesized by NEWT
321         }
322         @Override
323         public void windowGainedFocus(WindowEvent e) {
324             WindowDriver.this.focusChanged(false, true);
325         }
326         @Override
327         public void windowLostFocus(WindowEvent e) {
328             WindowDriver.this.focusChanged(false, false);
329         }
330         @Override
331         public void windowRepaint(WindowUpdateEvent e) {
332             if(null!=awtCanvas) {
333                 if(DEBUG_IMPLEMENTATION) {
334                     System.err.println("Window Repaint: "+awtCanvas);
335                 }
336                 WindowDriver.this.windowRepaint(false, 0, 0, getSurfaceWidth(), getSurfaceHeight());
337             }
338         }
339     }
340 }
http://JogAmp.org git info: FAQ, tutorial and man pages.