Jogamp
moved com.jogamp.javafx.* to com.jogamp.*.
[jogl.git] / src / newt / classes / com / jogamp / newt / awt / AWTWindow.java
1 /*
2  * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  * 
8  * - Redistribution of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * 
11  * - Redistribution in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  * 
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  * 
19  * This software is provided "AS IS," without a warranty of any kind. ALL
20  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23  * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26  * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27  * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28  * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29  * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30  * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  * 
32  */
33
34 package com.jogamp.newt.awt;
35
36 import java.awt.BorderLayout;
37 import java.awt.Canvas;
38 import java.awt.Container;
39 import java.awt.DisplayMode;
40 import java.awt.EventQueue;
41 import java.awt.Frame;
42 import java.awt.GraphicsDevice;
43 import java.awt.GraphicsEnvironment;
44 import java.lang.reflect.Method;
45 import java.lang.reflect.InvocationTargetException;
46 import java.awt.event.*;
47 import java.security.AccessController;
48 import java.security.PrivilegedAction;
49 import java.util.*;
50 import com.jogamp.newt.Window;
51 import java.awt.Insets;
52 import javax.media.nativewindow.*;
53 import javax.media.nativewindow.awt.*;
54
55 /** An implementation of the Newt Window class built using the
56     AWT. This is provided for convenience of porting to platforms
57     supporting Java SE. */
58
59 public class AWTWindow extends Window {
60
61     public AWTWindow() {
62         this(null);
63     }
64
65     public static Class[] getCustomConstructorArgumentTypes() {
66         return new Class[] { Container.class } ;
67     }
68
69     public AWTWindow(Container container) {
70         super();
71         title = "AWT NewtWindow";
72         this.container = container;
73         if(container instanceof Frame) {
74             frame = (Frame) container;
75         }
76     }
77
78     private boolean owningFrame;
79     private Container container = null;
80     private Frame frame = null; // same instance as container, just for impl. convenience
81     private AWTCanvas canvas;
82     // non fullscreen dimensions ..
83     private int nfs_width, nfs_height, nfs_x, nfs_y;
84
85     public void setTitle(final String title) {
86         super.setTitle(title);
87         runOnEDT(true, new Runnable() {
88                 public void run() {
89                     if (frame != null) {
90                         frame.setTitle(title);
91                     }
92                 }
93             });
94     }
95
96     protected void createNative(long parentWindowHandle, final Capabilities caps) {
97
98         if(0!=parentWindowHandle) {
99             throw new RuntimeException("Window parenting not supported in AWT, use AWTWindow(Frame) cstr for wrapping instead");
100         }
101
102         final AWTWindow awtWindow = this;
103
104         runOnEDT(true, new Runnable() {
105                 public void run() {
106                     if(null==container) {
107                         frame = new Frame();
108                         container = frame;
109                         owningFrame=true;
110                     } else {
111                         owningFrame=false;
112                         width = container.getWidth();
113                         height = container.getHeight();
114                         x = container.getX();
115                         y = container.getY();
116                     }
117                     if(null!=frame) {
118                         frame.setTitle(getTitle());
119                     }
120                     container.setLayout(new BorderLayout());
121                     canvas = new AWTCanvas(caps);
122                     Listener listener = new Listener(awtWindow);
123                     canvas.addMouseListener(listener);
124                     canvas.addMouseMotionListener(listener);
125                     canvas.addKeyListener(listener);
126                     canvas.addComponentListener(listener);
127                     container.add(canvas, BorderLayout.CENTER);
128                     container.setSize(width, height);
129                     container.setLocation(x, y);
130                     container.addComponentListener(new MoveListener(awtWindow));
131                     if(null!=frame) {
132                         frame.setUndecorated(undecorated||fullscreen);
133                         frame.addWindowListener(new WindowEventListener(awtWindow));
134                     }
135                 }
136             });
137     }
138
139     protected void closeNative() {
140         runOnEDT(true, new Runnable() {
141                 public void run() {
142                     if(owningFrame && null!=frame) {
143                         frame.dispose();
144                         owningFrame=false;
145                     }
146                     frame = null;
147                 }
148             });
149     }
150
151     public boolean hasDeviceChanged() {
152         boolean res = canvas.hasDeviceChanged();
153         if(res) {
154             config = canvas.getAWTGraphicsConfiguration();
155             if (config == null) {
156                 throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this);
157             }
158             updateDeviceData();
159         }
160         return res;
161     }
162
163     public void setVisible(final boolean visible) {
164         runOnEDT(true, new Runnable() {
165                 public void run() {
166                     container.setVisible(visible);
167                 }
168             });
169
170         config = canvas.getAWTGraphicsConfiguration();
171
172         if (config == null) {
173             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
174         }
175
176         updateDeviceData();
177     }
178
179     private void updateDeviceData() {
180         // propagate new info ..
181         ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)config.getScreen());
182         ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)config.getScreen().getDevice());
183
184         DisplayMode mode = ((AWTGraphicsDevice)config.getScreen().getDevice()).getGraphicsDevice().getDisplayMode();
185         int w = mode.getWidth();
186         int h = mode.getHeight();
187         ((AWTScreen)screen).setScreenSize(w, h);
188     }
189
190     public void setSize(final int width, final int height) {
191         this.width = width;
192         this.height = height;
193         if(!fullscreen) {
194             nfs_width=width;
195             nfs_height=height;
196         }
197         /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */
198         runOnEDT(false, new Runnable() {
199                 public void run() {
200                     Insets insets = container.getInsets();
201                     container.setSize(width + insets.left + insets.right,
202                                       height + insets.top + insets.bottom);
203                 }
204             });
205     }
206
207     public com.jogamp.newt.Insets getInsets() {
208         final int insets[] = new int[] { 0, 0, 0, 0 };
209         runOnEDT(true, new Runnable() {
210                 public void run() {
211                     Insets contInsets = container.getInsets();
212                     insets[0] = contInsets.top;
213                     insets[1] = contInsets.left;
214                     insets[2] = contInsets.bottom;
215                     insets[3] = contInsets.right;
216                 }
217             });
218         return new com.jogamp.newt.
219             Insets(insets[0],insets[1],insets[2],insets[3]);
220     }
221
222     public void setPosition(final int x, final int y) {
223         this.x = x;
224         this.y = y;
225         if(!fullscreen) {
226             nfs_x=x;
227             nfs_y=y;
228         }
229         runOnEDT(true, new Runnable() {
230                 public void run() {
231                     container.setLocation(x, y);
232                 }
233             });
234     }
235
236     public boolean setFullscreen(final boolean fullscreen) {
237         if(this.fullscreen!=fullscreen) {
238             final int x,y,w,h;
239             this.fullscreen=fullscreen;
240             if(fullscreen) {
241                 x = 0; y = 0;
242                 w = screen.getWidth();
243                 h = screen.getHeight();
244             } else {
245                 x = nfs_x;
246                 y = nfs_y;
247                 w = nfs_width;
248                 h = nfs_height;
249             }
250             if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
251                 System.err.println("AWTWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h);
252             }
253             /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */
254             runOnEDT(false, new Runnable() {
255                     public void run() {
256                         if(null!=frame) {
257                             if(!container.isDisplayable()) {
258                                 frame.setUndecorated(undecorated||fullscreen);
259                             } else {
260                                 if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
261                                     System.err.println("AWTWindow can't undecorate already created frame");
262                                 }
263                             }
264                         }
265                         container.setLocation(x, y);
266                         container.setSize(w, h);
267                     }
268                 });
269         }
270         return true;
271     }
272
273     public Object getWrappedWindow() {
274         return canvas;
275     }
276
277     protected void sendWindowEvent(int eventType) {
278         super.sendWindowEvent(eventType);
279     }
280
281     protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) {
282         super.sendKeyEvent(eventType, modifiers, keyCode, keyChar);
283     }
284
285     protected void sendMouseEvent(int eventType, int modifiers,
286                                   int x, int y, int button, int rotation) {
287         super.sendMouseEvent(eventType, modifiers, x, y, button, rotation);
288     }
289
290     private static void runOnEDT(boolean wait, Runnable r) {
291         if (EventQueue.isDispatchThread()) {
292             r.run();
293         } else {
294             try {
295                 if(wait) {
296                     EventQueue.invokeAndWait(r);
297                 } else {
298                     EventQueue.invokeLater(r);
299                 }
300             } catch (Exception e) {
301                 throw new NativeWindowException(e);
302             }
303         }
304     }
305
306     private static final int WINDOW_EVENT = 1;
307     private static final int KEY_EVENT = 2;
308     private static final int MOUSE_EVENT = 3;
309
310     class MoveListener implements ComponentListener {
311         private AWTWindow window;
312         private AWTDisplay display;
313
314         public MoveListener(AWTWindow w) {
315             window = w;
316             display = (AWTDisplay)window.getScreen().getDisplay();
317         }
318
319         public void componentResized(ComponentEvent e) {
320         }
321
322         public void componentMoved(ComponentEvent e) {
323             if(null!=container) {
324                 x = container.getX();
325                 y = container.getY();
326             }
327             display.enqueueEvent(window, com.jogamp.newt.WindowEvent.EVENT_WINDOW_MOVED, null);
328         }
329
330         public void componentShown(ComponentEvent e) {
331         }
332
333         public void componentHidden(ComponentEvent e) {
334         }
335
336     }
337
338     class Listener implements ComponentListener, MouseListener, MouseMotionListener, KeyListener {
339         private AWTWindow window;
340         private AWTDisplay display;
341
342         public Listener(AWTWindow w) {
343             window = w;
344             display = (AWTDisplay)window.getScreen().getDisplay();
345         }
346
347         public void componentResized(ComponentEvent e) {
348             width = canvas.getWidth();
349             height = canvas.getHeight();
350             display.enqueueEvent(window, com.jogamp.newt.WindowEvent.EVENT_WINDOW_RESIZED, null);
351         }
352
353         public void componentMoved(ComponentEvent e) {
354         }
355
356         public void componentShown(ComponentEvent e) {
357         }
358
359         public void componentHidden(ComponentEvent e) {
360         }
361
362         public void mouseClicked(MouseEvent e) {
363             // We ignore these as we synthesize them ourselves out of
364             // mouse pressed and released events
365         }
366
367         public void mouseEntered(MouseEvent e) {
368             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_ENTERED, e);
369         }
370
371         public void mouseExited(MouseEvent e) {
372             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_EXITED, e);
373         }
374
375         public void mousePressed(MouseEvent e) {
376             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_PRESSED, e);
377         }
378
379         public void mouseReleased(MouseEvent e) {
380             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_RELEASED, e);
381         }
382
383         public void mouseMoved(MouseEvent e) {
384             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_MOVED, e);
385         }
386
387         public void mouseDragged(MouseEvent e) {
388             display.enqueueEvent(window, com.jogamp.newt.MouseEvent.EVENT_MOUSE_DRAGGED, e);
389         }
390
391         public void keyPressed(KeyEvent e) {
392             display.enqueueEvent(window, com.jogamp.newt.KeyEvent.EVENT_KEY_PRESSED, e);
393         }
394
395         public void keyReleased(KeyEvent e) {
396             display.enqueueEvent(window, com.jogamp.newt.KeyEvent.EVENT_KEY_RELEASED, e);
397         }
398
399         public void keyTyped(KeyEvent e)  {
400             display.enqueueEvent(window, com.jogamp.newt.KeyEvent.EVENT_KEY_TYPED, e);
401         }
402     }
403
404     class WindowEventListener implements WindowListener {
405         private AWTWindow window;
406         private AWTDisplay display;
407
408         public WindowEventListener(AWTWindow w) {
409             window = w;
410             display = (AWTDisplay)window.getScreen().getDisplay();
411         }
412
413         public void windowActivated(WindowEvent e) {
414         }
415         public void windowClosed(WindowEvent e) {
416         }
417         public void windowClosing(WindowEvent e) {
418             display.enqueueEvent(window, com.jogamp.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY, null);
419         }
420         public void windowDeactivated(WindowEvent e) {
421         }
422         public void windowDeiconified(WindowEvent e) {
423         }
424         public void windowIconified(WindowEvent e) {
425         }
426         public void windowOpened(WindowEvent e) {
427         }
428     }
429 }
http://JogAmp.org git info: FAQ, tutorial and man pages.