From 969e427642d3b9be376cefaada9febd489b7b3d7 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 26 Jun 2010 06:59:48 +0300 Subject: GLAutoDrawable: setAnimator/getAnimator/invoke/display changes; NEWT: Adding native repaint; NewtCanvasAWT focus fix Support for native repaint, which shall call display() in case no animator is running. GLAutoDrawable invoke(GLRunnable) impl. handles case if invoked on animator thread, or no animator thread is running (issueing a display() call). The impl resides in GLDrawableHelper. GLEventListener's init() and glViewport()/reshape() method must be called before the 1st display() and after a dispose() call. It could miss the 1st display() call if added after the setVisible(true) call - due to the native repainting. The impl resides in GLDrawableHelper. The Animator un-/registers itself at the GLAutoDrawable via setAnimator. NEWT Window reparent always issues a resize() and display() call. NEWT native Window uses direct send.*Event for input events (again), instead of enqueueing it for performance. NEWT Window implements all status change and Java native event callbacks, instead of having duplicated code in all implementations. NewtCanvasAWT if the Newt window is focused, the AWT/Swing component[s] will loose the focus. --- src/newt/classes/com/jogamp/newt/Display.java | 27 +- src/newt/classes/com/jogamp/newt/Insets.java | 105 ----- src/newt/classes/com/jogamp/newt/Window.java | 523 ++++++++++++--------- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 118 ++++- .../classes/com/jogamp/newt/event/NEWTEvent.java | 2 +- .../com/jogamp/newt/event/NEWTEventConsumer.java | 43 ++ .../com/jogamp/newt/event/TraceWindowAdapter.java | 2 +- .../com/jogamp/newt/event/WindowAdapter.java | 2 +- .../com/jogamp/newt/event/WindowUpdateEvent.java | 53 +++ .../jogamp/newt/event/awt/AWTNewtEventFactory.java | 10 + .../newt/event/awt/AWTParentWindowAdapter.java | 13 + .../jogamp/newt/event/awt/AWTWindowAdapter.java | 22 +- .../com/jogamp/newt/impl/awt/AWTWindow.java | 17 +- .../com/jogamp/newt/impl/macosx/MacWindow.java | 55 +-- .../com/jogamp/newt/impl/opengl/kd/KDWindow.java | 11 +- .../jogamp/newt/impl/windows/WindowsWindow.java | 39 +- .../com/jogamp/newt/impl/x11/X11Window.java | 50 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 144 +++--- src/newt/classes/com/jogamp/newt/util/Insets.java | 105 +++++ 19 files changed, 769 insertions(+), 572 deletions(-) delete mode 100644 src/newt/classes/com/jogamp/newt/Insets.java create mode 100644 src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java create mode 100755 src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java create mode 100644 src/newt/classes/com/jogamp/newt/util/Insets.java (limited to 'src/newt/classes/com') diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 02c4733e7..deb4c7abe 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -182,10 +182,9 @@ public abstract class Display { return true; } public EDTUtil getEDTUtil() { - if( !edtQueried ) { + if( null == edtUtil ) { synchronized (this) { - if( !edtQueried ) { - edtQueried = true; + if( null == edtUtil ) { if(NewtFactory.useEDT()) { final Display f_dpy = this; Thread current = Thread.currentThread(); @@ -203,12 +202,11 @@ public abstract class Display { } return edtUtil; } - volatile boolean edtQueried = false; public void runOnEDTIfAvail(boolean wait, final Runnable task) { - EDTUtil edtUtil = getEDTUtil(); - if(runCreateAndDestroyOnEDT() && null!=edtUtil) { - edtUtil.invoke(wait, task); + EDTUtil _edtUtil = getEDTUtil(); + if(runCreateAndDestroyOnEDT() && null!=_edtUtil) { + _edtUtil.invoke(wait, task); } else { task.run(); } @@ -238,6 +236,7 @@ public abstract class Display { if(null!=edtUtil) { edtUtil.waitUntilStopped(); edtUtil=null; + edt=null; } aDevice = null; } else { @@ -318,11 +317,12 @@ public abstract class Display { private LinkedList/**/ events = new LinkedList(); protected void dispatchMessages() { - if(0==refCount) return; // we should not exist .. + if(0==refCount) return; // in destruction .. + + LinkedList/**/ _events = null; if(!events.isEmpty()) { // swap events list to free ASAP - LinkedList/**/ _events = null; synchronized(eventsLock) { if(!events.isEmpty()) { _events = events; @@ -335,10 +335,13 @@ public abstract class Display { NEWTEventTask eventTask = (NEWTEventTask) iter.next(); NEWTEvent event = eventTask.get(); Object source = event.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(event); + if(source instanceof NEWTEventConsumer) { + NEWTEventConsumer consumer = (NEWTEventConsumer) source ; + if(!consumer.consumeEvent(event)) { + enqueueEvent(false, event); + } } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + throw new RuntimeException("Event source not a NEWT one: "+source.getClass().getName()+", "+source); } eventTask.notifyIssuer(); } diff --git a/src/newt/classes/com/jogamp/newt/Insets.java b/src/newt/classes/com/jogamp/newt/Insets.java deleted file mode 100644 index e440892f0..000000000 --- a/src/newt/classes/com/jogamp/newt/Insets.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2009 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.jogamp.newt; - -/** - * Simple class representing insets. - * - * @author tdv - */ -public class Insets implements Cloneable { - public int top; - public int left; - public int bottom; - public int right; - - /** - * Creates and initializes a new Insets object with the - * specified top, left, bottom, and right insets. - * @param top the inset from the top. - * @param left the inset from the left. - * @param bottom the inset from the bottom. - * @param right the inset from the right. - */ - public Insets(int top, int left, int bottom, int right) { - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - /** - * Checks whether two insets objects are equal. Two instances - * of Insets are equal if the four integer values - * of the fields top, left, - * bottom, and right are all equal. - * @return true if the two insets are equal; - * otherwise false. - */ - public boolean equals(Object obj) { - if (obj instanceof Insets) { - Insets insets = (Insets)obj; - return ((top == insets.top) && (left == insets.left) && - (bottom == insets.bottom) && (right == insets.right)); - } - return false; - } - - /** - * Returns the hash code for this Insets. - * - * @return a hash code for this Insets. - */ - public int hashCode() { - int sum1 = left + bottom; - int sum2 = right + top; - int val1 = sum1 * (sum1 + 1)/2 + left; - int val2 = sum2 * (sum2 + 1)/2 + top; - int sum3 = val1 + val2; - return sum3 * (sum3 + 1)/2 + val2; - } - - public String toString() { - return getClass().getName() + "[top=" + top + ",left=" + left + - ",bottom=" + bottom + ",right=" + right + "]"; - } - - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new InternalError(); - } - } - -} diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 9bd4bb377..0cd5b31bc 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -34,11 +34,12 @@ package com.jogamp.newt; import com.jogamp.newt.event.*; +import com.jogamp.newt.util.*; import com.jogamp.newt.impl.Debug; -import com.jogamp.newt.util.EDTUtil; import com.jogamp.common.util.*; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.util.Rectangle; import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import java.util.ArrayList; @@ -46,7 +47,7 @@ import java.util.List; import java.util.Iterator; import java.lang.reflect.Method; -public abstract class Window implements NativeWindow +public abstract class Window implements NativeWindow, NEWTEventConsumer { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent"); @@ -155,7 +156,7 @@ public abstract class Window implements NativeWindow return 0 != windowHandle ; } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")"); + System.out.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } if(validateParentWindowHandle()) { Display dpy = getScreen().getDisplay(); @@ -163,7 +164,7 @@ public abstract class Window implements NativeWindow setVisibleImpl(true); } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.createNative() END ("+getThreadName()+", "+this+")"); + System.out.println("Window.createNative() END ("+getThreadName()+", "+this+")"); } return 0 != windowHandle ; } @@ -190,7 +191,7 @@ public abstract class Window implements NativeWindow } } catch (NativeWindowException nwe) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe); + System.out.println("Window.getNativeWindowHandle: not successful yet: "+nwe); } } finally { if(locked) { @@ -198,7 +199,7 @@ public abstract class Window implements NativeWindow } } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.getNativeWindowHandle: locked "+locked+", "+nativeWindow); + System.out.println("Window.getNativeWindowHandle: locked "+locked+", "+nativeWindow); } } return handle; @@ -245,7 +246,8 @@ public abstract class Window implements NativeWindow "\n, Visible "+isVisible()+ "\n, Undecorated "+undecorated+ "\n, Fullscreen "+fullscreen+ - "\n, WrappedWindow "+getWrappedWindow()); + "\n, WrappedWindow "+getWrappedWindow()+ + "\n, ChildWindows "+childWindows.size()); sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedListeners.size()+" ["); for (Iterator iter = surfaceUpdatedListeners.iterator(); iter.hasNext(); ) { @@ -376,41 +378,38 @@ public abstract class Window implements NativeWindow public void run() { windowLock(); try { - if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+this); + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+Window.this); } // Childs first .. - ArrayList listeners = null; - synchronized(childWindows) { - listeners = childWindows; - } - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + synchronized(childWindowsLock) { + for(Iterator i = childWindows.iterator(); i.hasNext(); ) { NativeWindow nw = (NativeWindow) i.next(); + System.out.println("Window.destroy(deep: "+deep+") CHILD BEGIN"); if(nw instanceof Window) { - ((Window)nw).destroy(deep); + ((Window)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + if(deep) { + ((Window)nw).destroy(deep); + } } else { nw.destroy(); } + System.out.println("Window.destroy(deep: "+deep+") CHILD END"); + } } // Now us .. if(deep) { - synchronized(childWindows) { + synchronized(childWindowsLock) { childWindows = new ArrayList(); } - synchronized(surfaceUpdatedListeners) { + synchronized(surfaceUpdatedListenersLock) { surfaceUpdatedListeners = new ArrayList(); } - synchronized(windowListeners) { - windowListeners = new ArrayList(); - } - synchronized(mouseListeners) { - mouseListeners = new ArrayList(); - } - synchronized(keyListeners) { - keyListeners = new ArrayList(); - } + windowListeners = new ArrayList(); + mouseListeners = new ArrayList(); + keyListeners = new ArrayList(); } Display dpy = null; Screen scr = null; @@ -428,8 +427,8 @@ public abstract class Window implements NativeWindow dpy.destroy(); } } - if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+this); + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+Window.this); } } finally { windowUnlock(); @@ -466,16 +465,16 @@ public abstract class Window implements NativeWindow try{ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { String msg = new String("!!! Window Invalidate(deep: "+deep+") "+getThreadName()); - System.err.println(msg); - //Exception e = new Exception(msg); - //e.printStackTrace(); + //System.out.println(msg); + Exception e = new Exception(msg); + e.printStackTrace(); } windowHandle = 0; - visible=false; - fullscreen=false; + visible = false; + fullscreen = false; if(deep) { - screen = null; + screen = null; parentWindowHandle = 0; parentNativeWindow = null; caps = null; @@ -593,43 +592,6 @@ public abstract class Window implements NativeWindow return false; } - /** - * If set to true, the default value, this NEWT Window implementation will - * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.
- * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}. - */ - public void setHandleDestroyNotify(boolean b) { - handleDestroyNotify = b; - } - - protected void windowDestroyNotify() { - if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyNotify START "+getThreadName()); - } - - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - - if(handleDestroyNotify && !isDestroyed()) { - destroy(); - } - - if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyeNotify END "+getThreadName()); - } - } - - protected void windowDestroyed() { - if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyed "+getThreadName()); - } - invalidate(); - } - - protected boolean reparentWindowImpl() { - // default implementation, no native reparenting support - return false; - } - class ReparentAction implements Runnable { NativeWindow newParent; Screen newScreen; @@ -652,7 +614,7 @@ public abstract class Window implements NativeWindow } if(DEBUG_IMPLEMENTATION) { - System.err.println("reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); + System.out.println("reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); } if(null!=parentNativeWindow && parentNativeWindow instanceof Window) { @@ -671,8 +633,16 @@ public abstract class Window implements NativeWindow x = 0; y = 0; } + getScreen().getDisplay().dispatchMessages(); // status up2date + boolean wasVisible = isVisible(); + if(wasVisible) { + Window.this.visible = false; + setVisibleImpl(false); + getScreen().getDisplay().dispatchMessages(); // status up2date + } boolean reparentRes = false; reparentRes = reparentWindowImpl(); + getScreen().getDisplay().dispatchMessages(); // status up2date if(!reparentRes) { parentWindowHandle = 0; @@ -680,11 +650,17 @@ public abstract class Window implements NativeWindow if( 0 != windowHandle ) { destroy(false); } + } else { + if(wasVisible) { + Window.this.visible = true; + setVisibleImpl(true); + getScreen().getDisplay().dispatchMessages(); // status up2date + } } } if(DEBUG_IMPLEMENTATION) { - System.err.println("reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + System.out.println("reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); } } finally { windowUnlock(); @@ -707,10 +683,10 @@ public abstract class Window implements NativeWindow public void reparentWindow(NativeWindow newParent, Screen newScreen) { if(!isDestroyed()) { runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); - // if( isVisible() ) { - enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - // enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_REPAINT); // trigger a repaint to listener - // } + if( isVisible() ) { + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + windowRepaint(0, 0, getWidth(), getHeight()); + } } } @@ -723,17 +699,15 @@ public abstract class Window implements NativeWindow windowLock(); try{ if( !isDestroyed() ) { - ArrayList listeners = null; - synchronized(childWindows) { - listeners = childWindows; - } - if(!visible && listeners.size()>0) { - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + if(!visible && childWindows.size()>0) { + synchronized(childWindowsLock) { + for(Iterator i = childWindows.iterator(); i.hasNext(); ) { NativeWindow nw = (NativeWindow) i.next(); if(nw instanceof Window) { ((Window)nw).setVisible(false); } } + } } if(0==windowHandle && visible) { Window.this.visible = visible; @@ -746,18 +720,20 @@ public abstract class Window implements NativeWindow setVisibleImpl(visible); } } - if(0!=windowHandle && visible && listeners.size()>0) { - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + if(0!=windowHandle && visible && childWindows.size()>0) { + synchronized(childWindowsLock) { + for(Iterator i = childWindows.iterator(); i.hasNext(); ) { NativeWindow nw = (NativeWindow) i.next(); if(nw instanceof Window) { ((Window)nw).setVisible(true); } } + } } } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); + System.out.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); } } finally { windowUnlock(); @@ -793,7 +769,7 @@ public abstract class Window implements NativeWindow public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { String msg = new String("Window setVisible: START ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); - //System.err.println(msg); + //System.out.println(msg); Exception ee = new Exception(msg); ee.printStackTrace(); } @@ -830,7 +806,7 @@ public abstract class Window implements NativeWindow try{ if(DEBUG_IMPLEMENTATION) { String msg = new String("Window setSize: START "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); - //System.err.println(msg); + //System.out.println(msg); Exception e = new Exception(msg); e.printStackTrace(); } @@ -847,7 +823,7 @@ public abstract class Window implements NativeWindow this.width = width; this.height = height; } else if ( 0 != windowHandle ) { - // this width/height will be set by windowChanged, called by X11 + // this width/height will be set by windowChanged, called by the native implementation setSizeImpl(width, height); } else { this.width = width; @@ -856,7 +832,7 @@ public abstract class Window implements NativeWindow } } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction); + System.out.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction); } } finally { windowUnlock(); @@ -881,7 +857,7 @@ public abstract class Window implements NativeWindow windowLock(); try{ if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); + System.out.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); } if ( this.x != x || this.y != y ) { if(!fullscreen) { @@ -918,7 +894,7 @@ public abstract class Window implements NativeWindow h = nfs_height; } if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()); + System.out.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()); } this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h); } @@ -934,12 +910,11 @@ public abstract class Window implements NativeWindow // private ArrayList childWindows = new ArrayList(); + private Object childWindowsLock = new Object(); protected void removeChild(NativeWindow win) { - synchronized(childWindows) { - ArrayList newChildWindows = (ArrayList) childWindows.clone(); - newChildWindows.remove(win); - childWindows = newChildWindows; + synchronized(childWindowsLock) { + childWindows.remove(win); } } @@ -947,16 +922,26 @@ public abstract class Window implements NativeWindow if (win == null) { return; } - synchronized(childWindows) { - ArrayList newChildWindows = (ArrayList) childWindows.clone(); - newChildWindows.add(win); - childWindows = newChildWindows; + synchronized(childWindowsLock) { + childWindows.add(win); } } // // Generic Event Support // + private void doEvent(boolean enqueue, boolean wait, com.jogamp.newt.event.NEWTEvent event) { + boolean done = false; + + if(!enqueue) { + done = consumeEvent(event); + wait = done; // don't wait if event can't be consumed now + } + + if(!done) { + enqueueEvent(wait, event); + } + } public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { if(!getInnerWindow().isDestroyed()) { @@ -964,21 +949,45 @@ public abstract class Window implements NativeWindow } } - public void sendEvent(NEWTEvent e) { + public boolean consumeEvent(NEWTEvent e) { + switch(e.getEventType()) { + case WindowEvent.EVENT_WINDOW_REPAINT: + if( windowIsLocked() ) { + if(!repaintQueued) { + repaintQueued=true; + return false; + } else { + return true; + } + } else { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.windowRepaint: "+e); + // Exception ee = new Exception("Window.windowRepaint: "+e); + // ee.printStackTrace(); + } + repaintQueued=false; + } + break; + default: + break; + } if(e instanceof WindowEvent) { - getInnerWindow().sendWindowEvent((WindowEvent)e); + getInnerWindow().consumeWindowEvent((WindowEvent)e); } else if(e instanceof KeyEvent) { - getInnerWindow().sendKeyEvent((KeyEvent)e); + getInnerWindow().consumeKeyEvent((KeyEvent)e); } else if(e instanceof MouseEvent) { - getInnerWindow().sendMouseEvent((MouseEvent)e); + getInnerWindow().consumeMouseEvent((MouseEvent)e); } + return true; } + protected boolean repaintQueued = false; // // SurfaceUpdatedListener Support // private ArrayList surfaceUpdatedListeners = new ArrayList(); + private Object surfaceUpdatedListenersLock = new Object(); /** * Appends the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} to the end of @@ -1004,13 +1013,11 @@ public abstract class Window implements NativeWindow if(l == null) { return; } - synchronized(surfaceUpdatedListeners) { + synchronized(surfaceUpdatedListenersLock) { if(0>index) { index = surfaceUpdatedListeners.size(); } - ArrayList newSurfaceUpdatedListeners = (ArrayList) surfaceUpdatedListeners.clone(); - newSurfaceUpdatedListeners.add(index, l); - surfaceUpdatedListeners = newSurfaceUpdatedListeners; + surfaceUpdatedListeners.add(index, l); } } @@ -1018,21 +1025,19 @@ public abstract class Window implements NativeWindow if (l == null) { return; } - synchronized(surfaceUpdatedListeners) { - ArrayList newSurfaceUpdatedListeners = (ArrayList) surfaceUpdatedListeners.clone(); - newSurfaceUpdatedListeners.remove(l); - surfaceUpdatedListeners = newSurfaceUpdatedListeners; + synchronized(surfaceUpdatedListenersLock) { + surfaceUpdatedListeners.remove(l); } } public void removeAllSurfaceUpdatedListener() { - synchronized(surfaceUpdatedListeners) { + synchronized(surfaceUpdatedListenersLock) { surfaceUpdatedListeners = new ArrayList(); } } public SurfaceUpdatedListener getSurfaceUpdatedListener(int index) { - synchronized(surfaceUpdatedListeners) { + synchronized(surfaceUpdatedListenersLock) { if(0>index) { index = surfaceUpdatedListeners.size()-1; } @@ -1041,19 +1046,17 @@ public abstract class Window implements NativeWindow } public SurfaceUpdatedListener[] getSurfaceUpdatedListeners() { - synchronized(surfaceUpdatedListeners) { + synchronized(surfaceUpdatedListenersLock) { return (SurfaceUpdatedListener[]) surfaceUpdatedListeners.toArray(); } } public void surfaceUpdated(Object updater, NativeWindow window, long when) { - ArrayList listeners = null; - synchronized(surfaceUpdatedListeners) { - listeners = surfaceUpdatedListeners; - } - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + synchronized(surfaceUpdatedListenersLock) { + for(Iterator i = surfaceUpdatedListeners.iterator(); i.hasNext(); ) { SurfaceUpdatedListener l = (SurfaceUpdatedListener) i.next(); l.surfaceUpdated(updater, window, when); + } } } @@ -1066,13 +1069,21 @@ public abstract class Window implements NativeWindow private int lastMouseClickCount = 0; // last mouse button click count public static final int ClickTimeout = 300; + public void sendMouseEvent(int eventType, int modifiers, + int x, int y, int button, int rotation) { + doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation); + } public void enqueueMouseEvent(boolean wait, int eventType, int modifiers, int x, int y, int button, int rotation) { + doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation); + } + private void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, + int x, int y, int button, int rotation) { if(x<0||y<0||x>=width||y>=height) { return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { - System.err.println("enqueueMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + System.out.println("doMouseEvent: enqueue"+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { @@ -1116,12 +1127,12 @@ public abstract class Window implements NativeWindow } else { e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0); } - screen.getDisplay().enqueueEvent(wait, e); + doEvent(enqueue, wait, e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.err.println("enqueueMouseEvent: synthesized MOUSE_CLICKED event"); + System.out.println("doMouseEvent: synthesized MOUSE_CLICKED event"); } - screen.getDisplay().enqueueEvent(wait, eClicked); + doEvent(enqueue, wait, eClicked); } } @@ -1148,52 +1159,41 @@ public abstract class Window implements NativeWindow if(l == null) { return; } - synchronized(mouseListeners) { - if(0>index) { - index = mouseListeners.size(); - } - ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); - newMouseListeners.add(index, l); - mouseListeners = newMouseListeners; + ArrayList clonedListeners = (ArrayList) mouseListeners.clone(); + if(0>index) { + index = clonedListeners.size(); } + clonedListeners.add(index, l); + mouseListeners = clonedListeners; } public void removeMouseListener(MouseListener l) { if (l == null) { return; } - synchronized(mouseListeners) { - ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); - newMouseListeners.remove(l); - mouseListeners = newMouseListeners; - } + ArrayList clonedListeners = (ArrayList) mouseListeners.clone(); + clonedListeners.remove(l); + mouseListeners = clonedListeners; } public MouseListener getMouseListener(int index) { - synchronized(mouseListeners) { - if(0>index) { - index = mouseListeners.size()-1; - } - return (MouseListener) mouseListeners.get(index); + ArrayList clonedListeners = (ArrayList) mouseListeners.clone(); + if(0>index) { + index = clonedListeners.size()-1; } + return (MouseListener) clonedListeners.get(index); } public MouseListener[] getMouseListeners() { - synchronized(mouseListeners) { - return (MouseListener[]) mouseListeners.toArray(); - } + return (MouseListener[]) mouseListeners.toArray(); } - protected void sendMouseEvent(MouseEvent e) { + protected void consumeMouseEvent(MouseEvent e) { if(DEBUG_MOUSE_EVENT) { - System.err.println("sendMouseEvent: event: "+e); + System.out.println("consumeMouseEvent: event: "+e); } - ArrayList listeners = null; - synchronized(mouseListeners) { - listeners = mouseListeners; - } - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + for(Iterator i = mouseListeners.iterator(); i.hasNext(); ) { MouseListener l = (MouseListener) i.next(); switch(e.getEventType()) { case MouseEvent.EVENT_MOUSE_CLICKED: @@ -1230,10 +1230,12 @@ public abstract class Window implements NativeWindow // KeyListener/Event Support // + public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) ); + } + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { - screen.getDisplay().enqueueEvent(wait, - new KeyEvent(eventType, this, System.currentTimeMillis(), - modifiers, keyCode, keyChar) ); + enqueueEvent(wait, new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) ); } /** @@ -1258,53 +1260,42 @@ public abstract class Window implements NativeWindow if(l == null) { return; } - synchronized(keyListeners) { - if(0>index) { - index = keyListeners.size(); - } - ArrayList newKeyListeners = (ArrayList) keyListeners.clone(); - newKeyListeners.add(index, l); - keyListeners = newKeyListeners; + ArrayList clonedListeners = (ArrayList) keyListeners.clone(); + if(0>index) { + index = clonedListeners.size(); } + clonedListeners.add(index, l); + keyListeners = clonedListeners; } public void removeKeyListener(KeyListener l) { if (l == null) { return; } - synchronized(keyListeners) { - ArrayList newKeyListeners = (ArrayList) keyListeners.clone(); - newKeyListeners.remove(l); - keyListeners = newKeyListeners; - } + ArrayList clonedListeners = (ArrayList) keyListeners.clone(); + clonedListeners.remove(l); + keyListeners = clonedListeners; } public KeyListener getKeyListener(int index) { - synchronized(keyListeners) { - if(0>index) { - index = keyListeners.size()-1; - } - return (KeyListener) keyListeners.get(index); + ArrayList clonedListeners = (ArrayList) keyListeners.clone(); + if(0>index) { + index = clonedListeners.size()-1; } + return (KeyListener) clonedListeners.get(index); } public KeyListener[] getKeyListeners() { - synchronized(keyListeners) { - return (KeyListener[]) keyListeners.toArray(); - } + return (KeyListener[]) keyListeners.toArray(); } private ArrayList keyListeners = new ArrayList(); - protected void sendKeyEvent(KeyEvent e) { + protected void consumeKeyEvent(KeyEvent e) { if(DEBUG_KEY_EVENT) { - System.err.println("sendKeyEvent: "+e); - } - ArrayList listeners = null; - synchronized(keyListeners) { - listeners = keyListeners; + System.out.println("consumeKeyEvent: "+e); } - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + for(Iterator i = keyListeners.iterator(); i.hasNext(); ) { KeyListener l = (KeyListener) i.next(); switch(e.getEventType()) { case KeyEvent.EVENT_KEY_PRESSED: @@ -1325,10 +1316,12 @@ public abstract class Window implements NativeWindow // // WindowListener/Event Support // + public void sendWindowEvent(int eventType) { + consumeWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) ); + } + public void enqueueWindowEvent(boolean wait, int eventType) { - WindowEvent event = new WindowEvent(eventType, this, System.currentTimeMillis()); - screen.getDisplay().enqueueEvent( wait, event ); - // sendWindowEvent ( event ); // FIXME: Think about performance/lag .. ? + enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) ); } private ArrayList windowListeners = new ArrayList(); @@ -1357,55 +1350,40 @@ public abstract class Window implements NativeWindow if(l == null) { return; } - synchronized(windowListeners) { - if(0>index) { - index = windowListeners.size(); - } - ArrayList newWindowListeners = (ArrayList) windowListeners.clone(); - newWindowListeners.add(index, l); - windowListeners = newWindowListeners; + ArrayList clonedListeners = (ArrayList) windowListeners.clone(); + if(0>index) { + index = clonedListeners.size(); } + clonedListeners.add(index, l); + windowListeners = clonedListeners; } public void removeWindowListener(WindowListener l) { if (l == null) { return; } - synchronized(windowListeners) { - ArrayList newWindowListeners = (ArrayList) windowListeners.clone(); - newWindowListeners.remove(l); - windowListeners = newWindowListeners; - } + ArrayList clonedListeners = (ArrayList) windowListeners.clone(); + clonedListeners.remove(l); + windowListeners = clonedListeners; } public WindowListener getWindowListener(int index) { - synchronized(windowListeners) { - if(0>index) { - index = windowListeners.size()-1; - } - return (WindowListener) windowListeners.get(index); + ArrayList clonedListeners = (ArrayList) windowListeners.clone(); + if(0>index) { + index = clonedListeners.size()-1; } + return (WindowListener) clonedListeners.get(index); } public WindowListener[] getWindowListeners() { - synchronized(windowListeners) { - return (WindowListener[]) windowListeners.toArray(); - } - } - - protected void sendWindowEvent(WindowEvent e) { - getInnerWindow().sendWindowEvent(e, 0, 0, 0, 0); + return (WindowListener[]) windowListeners.toArray(); } - protected void sendWindowEvent(WindowEvent e, int p1, int p2, int p3, int p4) { + protected void consumeWindowEvent(WindowEvent e) { if(DEBUG_WINDOW_EVENT) { - System.err.println("sendWindowEvent: "+e+", "+p1+", "+p2+", "+p3+", "+p4); + System.out.println("consumeWindowEvent: "+e); } - ArrayList listeners = null; - synchronized(windowListeners) { - listeners = windowListeners; - } - for(Iterator i = listeners.iterator(); i.hasNext(); ) { + for(Iterator i = windowListeners.iterator(); i.hasNext(); ) { WindowListener l = (WindowListener) i.next(); switch(e.getEventType()) { case WindowEvent.EVENT_WINDOW_RESIZED: @@ -1423,9 +1401,9 @@ public abstract class Window implements NativeWindow case WindowEvent.EVENT_WINDOW_LOST_FOCUS: l.windowLostFocus(e); break; - //case WindowEvent.EVENT_WINDOW_REPAINT: - // l.windowRepaint(e); - // break; + case WindowEvent.EVENT_WINDOW_REPAINT: + l.windowRepaint((WindowUpdateEvent)e); + break; default: throw new NativeWindowException("Unexpected window event type " @@ -1434,6 +1412,115 @@ public abstract class Window implements NativeWindow } } + /** + * @param focusGained + */ + protected void focusChanged(boolean focusGained) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.focusChanged: "+focusGained); + } + if (focusGained) { + sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + } else { + sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + } + } + + protected void visibleChanged(boolean visible) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.visibleChanged: "+this.visible+" -> "+visible); + } + this.visible = visible ; + } + + protected void sizeChanged(int newWidth, int newHeight) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.sizeChanged: "+width+"x"+height+" -> "+newWidth+"x"+newHeight); + } + if(width != newWidth || height != newHeight) { + width = newWidth; + height = newHeight; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + } + } + + protected void positionChanged(int newX, int newY) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.positionChanged: "+x+"/"+y+" -> "+newX+"/"+newY); + } + if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { + x = newX; + y = newY; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + } + } + + /** + * If set to true, the default value, this NEWT Window implementation will + * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.
+ * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}. + */ + public void setHandleDestroyNotify(boolean b) { + handleDestroyNotify = b; + } + + protected void windowDestroyNotify() { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.windowDestroyNotify START "+getThreadName()); + } + + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + + if(handleDestroyNotify && !isDestroyed()) { + destroy(); + } + + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.windowDestroyeNotify END "+getThreadName()); + } + } + + protected void windowDestroyed() { + if(DEBUG_IMPLEMENTATION) { + System.out.println("Window.windowDestroyed "+getThreadName()); + } + invalidate(); + } + + public void setPropagateRepaint(boolean v) { + propagateRepaint = v; + } + protected boolean propagateRepaint = true; + + public void windowRepaint(int x, int y, int width, int height) { + if(!propagateRepaint) { + return; + } + if(0>width) { + width=this.width; + } + if(0>height) { + height=this.height; + } + + NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(), + new Rectangle(x, y, width, height)); + doEvent(false, false, e); + } + + protected boolean reparentWindowImpl() { + // default implementation, no native reparenting support + return false; + } + // // Reflection helper .. // diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 8944c03bb..b2dd719bc 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -35,13 +35,20 @@ package com.jogamp.newt.awt; import java.lang.reflect.*; import java.security.*; +import java.awt.Button; +import java.awt.Frame; import java.awt.Canvas; +import java.awt.Graphics; +import java.awt.KeyboardFocusManager; import javax.media.nativewindow.*; -// import javax.media.nativewindow.awt.*; import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.impl.Debug; @@ -52,6 +59,7 @@ public class NewtCanvasAWT extends java.awt.Canvas { NativeWindow parent = null; Window newtChild = null; AWTAdapter awtAdapter = null; + boolean hasSwingContainer = false; /** * Instantiates a NewtCanvas without a NEWT child.
@@ -67,11 +75,84 @@ public class NewtCanvasAWT extends java.awt.Canvas { super(); setNEWTChild(child); } + + class UnfocusRunnable implements Runnable { + boolean focusTraversed = false; + public void run() { + KeyboardFocusManager focusManager = + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + java.awt.Component comp1 = focusManager.getPermanentFocusOwner(); + java.awt.Component comp2 = focusManager.getFocusOwner(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT Unfocus: traversed "+focusTraversed+" (1)"); + System.out.println("PRE PermenetFocusOwner: "+comp1); + System.out.println("PRE FocusOwner: "+comp2); + } + if(null!=comp1) { + if(!focusTraversed && null==comp2) { + comp1.requestFocus(); + focusTraversed=true; + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT Unfocus: traversed "+focusTraversed+" (*)"); + } + } else { + focusTraversed=false; + } + + if(DEBUG_IMPLEMENTATION) { + comp1 = focusManager.getPermanentFocusOwner(); + comp2 = focusManager.getFocusOwner(); + System.out.println("MID PermenetFocusOwner: "+comp1); + System.out.println("MID FocusOwner: "+comp2); + } + + focusManager.clearGlobalFocusOwner(); + + if(DEBUG_IMPLEMENTATION) { + comp1 = focusManager.getPermanentFocusOwner(); + comp2 = focusManager.getFocusOwner(); + System.out.println("POST PermenetFocusOwner: "+comp1); + System.out.println("POST FocusOwner: "+comp2); + } + + if(focusTraversed && null!=newtChild) { + newtChild.requestFocus(); + } + } + } + } + UnfocusRunnable unfocusRunnable = new UnfocusRunnable(); + + class FocusListener extends WindowAdapter { + public synchronized void windowGainedFocus(WindowEvent e) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtCanvasAWT focus on: AWT focus "+ NewtCanvasAWT.this.hasFocus()+ + ", focusable "+NewtCanvasAWT.this.isFocusable()+", onEDT "+hasSwingContainer); + } + if(hasSwingContainer) { + java.awt.EventQueue.invokeLater(unfocusRunnable); + } else { + unfocusRunnable.run(); + } + } + public synchronized void windowLostFocus(WindowEvent e) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtCanvasAWT focus off: AWT focus "+ NewtCanvasAWT.this.hasFocus()); + } + } + } + FocusListener focusListener = new FocusListener(); /** sets a new NEWT child, provoking reparenting on the NEWT level. */ public NewtCanvasAWT setNEWTChild(Window child) { if(newtChild!=child) { + if(null!=newtChild) { + newtChild.removeWindowListener(focusListener); + } newtChild = child; + if(null!=newtChild) { + newtChild.addWindowListener(focusListener); + } if(null!=parent) { java.awt.Container cont = getContainer(this); // reparent right away, addNotify has been called already @@ -100,12 +181,22 @@ public class NewtCanvasAWT extends java.awt.Canvas { } } - static java.awt.Container getContainer(java.awt.Component comp) { - while( null != comp && !(comp instanceof java.awt.Container) ) { + static boolean hasSwingContainer(java.awt.Component comp) { + while( null != comp ) { + if( comp instanceof javax.swing.JComponent ) { + return true; + } comp = comp.getParent(); } - if(comp instanceof java.awt.Container) { - return (java.awt.Container) comp; + return false; + } + + static java.awt.Container getContainer(java.awt.Component comp) { + while( null != comp ) { + if( comp instanceof java.awt.Container ) { + return (java.awt.Container) comp; + } + comp = comp.getParent(); } return null; } @@ -113,11 +204,13 @@ public class NewtCanvasAWT extends java.awt.Canvas { public void addNotify() { super.addNotify(); disableBackgroundErase(); + hasSwingContainer = hasSwingContainer(this); java.awt.Container cont = getContainer(this); if(DEBUG_IMPLEMENTATION) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. - System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+" -> "+cont); + System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+ + ", displayable "+isDisplayable()+", swingContainer "+hasSwingContainer+" -> "+cont); } reparentWindow(true, cont); } @@ -154,6 +247,8 @@ public class NewtCanvasAWT extends java.awt.Canvas { newtChild.reparentWindow(parent, screen); newtChild.setVisible(true); setWindowAdapter(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + newtChild.windowRepaint(0, 0, newtChild.getWidth(), newtChild.getHeight()); } } else { setWindowAdapter(false); @@ -164,9 +259,14 @@ public class NewtCanvasAWT extends java.awt.Canvas { } public void paint(Graphics g) { - if(null!=newtChild) { - // enqueueWindowEvent(true, WindowEvent.EVENT_WINDOW_REPAINT); // trigger a repaint to listener - } + if(null!=newtChild) { + newtChild.windowRepaint(0, 0, getWidth(), getHeight()); + } + } + public void update(Graphics g) { + if(null!=newtChild) { + newtChild.windowRepaint(0, 0, getWidth(), getHeight()); + } } // Disables the AWT's erasing of this Canvas's background on Windows diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index 476b3640e..9afcb840c 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -123,7 +123,7 @@ public class NEWTEvent extends java.util.EventObject { /** * Attach the passed object to this event.
- * If an object was previously attached, it will replaced.
+ * If an object was previously attached, it will be replaced.
* Attachments to NEWT events allow users to pass on information * from one custom listener to another, ie custom listener to listener * communication. diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java new file mode 100644 index 000000000..e37c820a1 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEventConsumer.java @@ -0,0 +1,43 @@ +/* + * 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; + +public interface NEWTEventConsumer { + + /** + * Consume the event + * + * @return true if the event can be consumed now, + * otherwise propagate it later. + */ + public boolean consumeEvent(NEWTEvent event); +} diff --git a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java index a6cf0d6ed..fb9e1877a 100644 --- a/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/TraceWindowAdapter.java @@ -65,7 +65,7 @@ public class TraceWindowAdapter implements WindowListener { System.out.println(e); if(null!=downstream) { downstream.windowLostFocus(e); } } - public void windowRepaint(WindowEvent e) { + public void windowRepaint(WindowUpdateEvent e) { System.out.println(e); if(null!=downstream) { downstream.windowRepaint(e); } } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java index 925bc7113..587622a81 100644 --- a/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/WindowAdapter.java @@ -45,6 +45,6 @@ public abstract class WindowAdapter implements WindowListener } public void windowLostFocus(WindowEvent e) { } - public void windowRepaint(WindowEvent e) { + public void windowRepaint(WindowUpdateEvent e) { } } diff --git a/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java new file mode 100755 index 000000000..5a11f0f77 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/event/WindowUpdateEvent.java @@ -0,0 +1,53 @@ +/* + * 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; + +import com.jogamp.newt.*; +import com.jogamp.nativewindow.util.Rectangle; + +public class WindowUpdateEvent extends WindowEvent { + Rectangle bounds; + + public WindowUpdateEvent(int eventType, Object source, long when, Rectangle bounds) + { + super(eventType, source, when); + this.bounds = bounds; + } + + public Rectangle getBounds() { + return bounds; + } + + public String toString() { + return "WindowUpdateEvent["+super.toString()+", "+bounds+"]"; + } +} diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java index e4e97946a..076165c73 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTNewtEventFactory.java @@ -48,8 +48,10 @@ class AWTNewtEventFactory { // n/a map.put(java.awt.event.WindowEvent.WINDOW_DEICONIFIED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_DEICONIFIED); map.put(java.awt.event.WindowEvent.WINDOW_ACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS); map.put(java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + map.put(java.awt.event.FocusEvent.FOCUS_GAINED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_GAINED_FOCUS); map.put(java.awt.event.WindowEvent.WINDOW_DEACTIVATED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS); map.put(java.awt.event.WindowEvent.WINDOW_LOST_FOCUS, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS); + map.put(java.awt.event.FocusEvent.FOCUS_LOST, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_LOST_FOCUS); // n/a map.put(java.awt.event.WindowEvent.WINDOW_STATE_CHANGED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_STATE_CHANGED); map.put(java.awt.event.ComponentEvent.COMPONENT_MOVED, com.jogamp.newt.event.WindowEvent.EVENT_WINDOW_MOVED); @@ -108,6 +110,14 @@ class AWTNewtEventFactory { return null; // no mapping .. } + static final com.jogamp.newt.event.WindowEvent createWindowEvent(java.awt.event.FocusEvent event, com.jogamp.newt.Window newtSource) { + int type = eventTypeAWT2NEWT.get(event.getID()); + if(-1 < type) { + return new com.jogamp.newt.event.WindowEvent(type, (null==newtSource)?(Object)event.getComponent():(Object)newtSource, System.currentTimeMillis()); + } + return null; // no mapping .. + } + static final com.jogamp.newt.event.MouseEvent createMouseEvent(java.awt.event.MouseEvent event, com.jogamp.newt.Window newtSource) { int type = eventTypeAWT2NEWT.get(event.getID()); if(-1 < type) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 7905a728c..43087289a 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -53,6 +53,19 @@ public class AWTParentWindowAdapter return super.removeFrom(awtComponent); } + public void focusGained(java.awt.event.FocusEvent e) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT: focusGained: START "+ e.getComponent()); + } + newtWindow.requestFocus(); + } + + public void focusLost(java.awt.event.FocusEvent e) { + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT: focusLost: "+ e.getComponent()); + } + } + public void componentResized(java.awt.event.ComponentEvent e) { // Need to resize the NEWT child window // the resized event will be send via the native window feedback. diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 7bfffbafc..875401544 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -33,7 +33,7 @@ package com.jogamp.newt.event.awt; public class AWTWindowAdapter extends AWTAdapter - implements java.awt.event.ComponentListener, java.awt.event.WindowListener + implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.FocusListener { WindowClosingListener windowClosingListener; @@ -52,6 +52,7 @@ public class AWTWindowAdapter public AWTAdapter addTo(java.awt.Component awtComponent) { java.awt.Window win = getWindow(awtComponent); awtComponent.addComponentListener(this); + awtComponent.addFocusListener(this); if( null == windowClosingListener ) { windowClosingListener = new WindowClosingListener(); } @@ -65,6 +66,7 @@ public class AWTWindowAdapter } public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeFocusListener(this); awtComponent.removeComponentListener(this); java.awt.Window win = getWindow(awtComponent); if( null != win && null != windowClosingListener ) { @@ -86,6 +88,24 @@ public class AWTWindowAdapter return null; } + public void focusGained(java.awt.event.FocusEvent e) { + com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(null!=newtListener) { + ((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event); + } else { + enqueueEvent(false, event); + } + } + + public void focusLost(java.awt.event.FocusEvent e) { + com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(null!=newtListener) { + ((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event); + } else { + enqueueEvent(false, event); + } + } + public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index a06b7160c..6f936d2c6 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -215,7 +215,7 @@ public class AWTWindow extends Window { } } - public com.jogamp.newt.Insets getInsets() { + public com.jogamp.newt.util.Insets getInsets() { final int insets[] = new int[] { 0, 0, 0, 0 }; runOnEDT(true, new Runnable() { public void run() { @@ -226,7 +226,7 @@ public class AWTWindow extends Window { insets[3] = contInsets.right; } }); - return new com.jogamp.newt. + return new com.jogamp.newt.util. Insets(insets[0],insets[1],insets[2],insets[3]); } @@ -264,19 +264,6 @@ public class AWTWindow extends Window { return canvas; } - protected void enqueueWindowEvent(int eventType) { - super.enqueueWindowEvent(eventType); - } - - protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - super.enqueueKeyEvent(eventType, modifiers, keyCode, keyChar); - } - - protected void enqueueMouseEvent(int eventType, int modifiers, - int x, int y, int button, int rotation) { - super.enqueueMouseEvent(eventType, modifiers, x, y, button, rotation); - } - private void runOnEDT(boolean wait, Runnable r) { EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); if ( ( null != edtUtil && edtUtil.isCurrentThreadEDT() ) || EventQueue.isDispatchThread() ) { diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 8a656a5a8..9f47aa49f 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -39,6 +39,7 @@ import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import com.jogamp.newt.*; import com.jogamp.newt.event.*; import com.jogamp.newt.impl.*; +import com.jogamp.newt.util.*; public class MacWindow extends Window { @@ -295,24 +296,6 @@ public class MacWindow extends Window { return fullscreen; } - private void sizeChanged(int newWidth, int newHeight) { - if(width != newWidth || height != newHeight) { - if (DEBUG_IMPLEMENTATION) { - System.out.println(Thread.currentThread().getName()+" Size changed to " + newWidth + ", " + newHeight); - } - width = newWidth; - height = newHeight; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } - if (DEBUG_IMPLEMENTATION) { - System.out.println(" Posted WINDOW_RESIZED event"); - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - } - } - private void insetsChanged(int left, int top, int right, int bottom) { if (DEBUG_IMPLEMENTATION) { System.out.println(Thread.currentThread().getName()+ @@ -326,32 +309,6 @@ public class MacWindow extends Window { } } - private void positionChanged(int newX, int newY) { - if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { - if (DEBUG_IMPLEMENTATION) { - System.out.println(Thread.currentThread().getName()+" Position changed to " + newX + ", " + newY); - } - x = newX; - y = newY; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } - if (DEBUG_IMPLEMENTATION) { - System.out.println(" Posted WINDOW_MOVED event"); - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); - } - } - - private void focusChanged(boolean focusGained) { - if (focusGained) { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); - } else { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); - } - } - private char convertKeyChar(char keyChar) { if (keyChar == '\r') { // Turn these into \n @@ -435,12 +392,12 @@ public class MacWindow extends Window { return keyChar; } - protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { int key = convertKeyChar(keyChar); if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()); // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system - super.enqueueKeyEvent(eventType, modifiers, key, keyChar); + super.enqueueKeyEvent(wait, eventType, modifiers, key, keyChar); } private void createWindow(final boolean recreate, final int x, final int y, final int width, final int height, final boolean fullscreen) { @@ -482,9 +439,9 @@ public class MacWindow extends Window { ie.printStackTrace(); } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_GAINED_FOCUS); } protected static native boolean initIDs0(); diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 0d12a4a0a..0c7254376 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -126,16 +126,11 @@ public class KDWindow extends Window { windowUserData=userData; } - private void sizeChanged(int newWidth, int newHeight) { - width = newWidth; - height = newHeight; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } else { + protected void sizeChanged(int newWidth, int newHeight) { + if(fullscreen) { ((KDScreen)screen).setScreenSize(width, height); } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + super.sizeChanged(newWidth, newHeight); } private long eglWindowHandle; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index aedb4ed7d..47f79f46a 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -36,6 +36,7 @@ package com.jogamp.newt.impl.windows; import javax.media.nativewindow.*; import com.jogamp.newt.*; import com.jogamp.newt.event.*; +import com.jogamp.newt.util.*; public class WindowsWindow extends Window { @@ -216,42 +217,4 @@ public class WindowsWindow extends Window { insets.bottom = bottom; } } - - private void sizeChanged(int newWidth, int newHeight) { - if(width != newWidth || height != newHeight) { - width = newWidth; - height = newHeight; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - } - } - - private void positionChanged(int newX, int newY) { - if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { - x = newX; - y = newY; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); - } - } - - /** - * - * @param focusOwner if focusGained is true, focusOwner is the previous - * focus owner, if focusGained is false, focusOwner is the new focus owner - * @param focusGained - */ - private void focusChanged(long focusOwner, boolean focusGained) { - if (focusGained) { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); - } else { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); - } - } } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index e7fc96019..6890b29fa 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -71,7 +71,8 @@ public class X11Window extends Window { if(0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); try { - CloseWindow0(display.getHandle(), windowHandleClose, display.getJavaObjectAtom()); + CloseWindow0(display.getHandle(), windowHandleClose, + display.getJavaObjectAtom(), display.getWindowDeleteAtom()); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); @@ -134,7 +135,7 @@ public class X11Window extends Window { private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, long visualID, long javaObjectAtom, long windowDeleteAtom, int x, int y, int width, int height, boolean undecorated); - private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom); + private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); private native void setVisible0(long display, long windowHandle, boolean visible); private native void setSize0(long display, long windowHandle, int width, int height); private native void setPosSizeDecor0(long parentWindowHandle, long display, int screen_index, long windowHandle, @@ -145,51 +146,6 @@ public class X11Window extends Window { private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, int x, int y, boolean undecorated, boolean isVisible); - private void windowChanged(int newX, int newY, int newWidth, int newHeight) { - if(width != newWidth || height != newHeight) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window windowChanged size: "+this.width+"x"+this.height+" -> "+newWidth+"x"+newHeight); - } - width = newWidth; - height = newHeight; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - } - if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window windowChanged position: "+this.x+"/"+this.y+" -> "+newX+"x"+newY); - } - x = newX; - y = newY; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); - } - } - - /** - * @param focusGained - */ - private void focusChanged(boolean focusGained) { - if (focusGained) { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); - } else { - enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); - } - } - - /** - * @param focusGained - */ - private void visibleChanged(boolean visible) { - // FIXME .. this.visible = visible ; - } - private void windowCreated(long windowHandle) { this.windowHandle = windowHandle; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index e36e516df..e66ed1e34 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -35,6 +35,7 @@ package com.jogamp.newt.opengl; import com.jogamp.newt.*; import com.jogamp.newt.event.*; +import com.jogamp.newt.util.*; import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import javax.media.nativewindow.*; import javax.media.opengl.*; @@ -55,22 +56,34 @@ import java.util.*; */ public class GLWindow extends Window implements GLAutoDrawable { private Window window; - private boolean runPumpMessages; /** * Constructor. Do not call this directly -- use {@link #create()} instead. */ protected GLWindow(Window window) { + this.startTime = System.currentTimeMillis(); this.window = window; this.window.setHandleDestroyNotify(false); - this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ; window.addWindowListener(new WindowAdapter() { + public void windowRepaint(WindowUpdateEvent e) { + if( !windowIsLocked() && null == getAnimator() ) { + display(); + } + } + public void windowResized(WindowEvent e) { sendReshape = true; + if( !windowIsLocked() && null == getAnimator() ) { + display(); + } } public void windowDestroyNotify(WindowEvent e) { - sendDestroy = true; + if( !windowIsLocked() && null == getAnimator() ) { + destroy(); + } else { + sendDestroy = true; + } } }); } @@ -128,31 +141,6 @@ public class GLWindow extends Window implements GLAutoDrawable { return window.getWrappedWindow(); } - /** - * EXPERIMENTAL
- * Enable or disables running the {@link Display#pumpMessages} in the {@link #display()} call.
- * The default behavior is to run {@link Display#pumpMessages}.

- * - * The idea was that in a single threaded environment with one {@link Display} and many {@link Window}'s, - * a performance benefit was expected while disabling the implicit {@link Display#pumpMessages} and - * do it once via {@link GLWindow#runCurrentThreadPumpMessage()}
- * This could not have been verified. No measurable difference could have been recognized.

- * - * Best performance has been achieved with one GLWindow per thread.
- * - * Enabling local pump messages while using the EDT, - * {@link com.jogamp.newt.NewtFactory#setUseEDT(boolean)}, - * will result in an exception. - * - * @deprecated EXPERIMENTAL, semantic is about to be removed after further verification. - */ - public void setRunPumpMessages(boolean onoff) { - if( onoff && null!=getScreen().getDisplay().getEDTUtil() ) { - throw new GLException("GLWindow.setRunPumpMessages(true) - Can't do with EDT on"); - } - runPumpMessages = onoff; - } - protected void createNativeImpl() { shouldNotCallThis(); } @@ -178,7 +166,7 @@ public class GLWindow extends Window implements GLAutoDrawable { // Lock: Have to cover whole workflow (dispose all, context, drawable and window) windowLock(); try { - if(null==window || window.isDestroyed()) { + if( isDestroyed() ) { return; // nop } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { @@ -186,21 +174,20 @@ public class GLWindow extends Window implements GLAutoDrawable { e1.printStackTrace(); } - if ( null != context && context.isCreated() && null != drawable && drawable.isRealized() ) { - // Catch dispose GLExceptions by GLEventListener, just 'print' them - // so we can continue with the destruction. - try { - helper.invokeGL(drawable, context, disposeAction, null); - } catch (GLException gle) { - gle.printStackTrace(); + if( window.isNativeWindowValid() && null != drawable && drawable.isRealized() ) { + if( null != context && context.isCreated() ) { + // Catch dispose GLExceptions by GLEventListener, just 'print' them + // so we can continue with the destruction. + try { + helper.invokeGL(drawable, context, disposeAction, null); + } catch (GLException gle) { + gle.printStackTrace(); + } + + context.destroy(); + context = null; } - } - if (context != null && null != drawable && drawable.isRealized() ) { - context.destroy(); - context = null; - } - if (drawable != null) { drawable.setRealized(false); drawable = null; } @@ -228,7 +215,7 @@ public class GLWindow extends Window implements GLAutoDrawable { * @see #destroy() */ public void destroy(boolean deep) { - if(!isDestroyed()) { + if( !isDestroyed() ) { runOnEDTIfAvail(true, new DestroyAction(deep)); } } @@ -369,6 +356,13 @@ public class GLWindow extends Window implements GLAutoDrawable { return window.isFullscreen(); } + public void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { + window.enqueueEvent(wait, event); + } + public boolean consumeEvent(NEWTEvent e) { + return window.consumeEvent(e); + } + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) { window.addSurfaceUpdatedListener(index, l); } @@ -414,6 +408,12 @@ public class GLWindow extends Window implements GLAutoDrawable { return window.getKeyListeners(); } + public void sendWindowEvent(int eventType) { + window.sendWindowEvent(eventType); + } + public void enqueueWindowEvent(boolean wait, int eventType) { + window.enqueueWindowEvent(wait, eventType); + } public void addWindowListener(int index, WindowListener l) { window.addWindowListener(index, l); } @@ -426,6 +426,12 @@ public class GLWindow extends Window implements GLAutoDrawable { public WindowListener[] getWindowListeners() { return window.getWindowListeners(); } + public void setPropagateRepaint(boolean v) { + window.setPropagateRepaint(v); + } + public void windowRepaint(int x, int y, int width, int height) { + window.windowRepaint(x, y, width, height); + } public String toString() { return "NEWT-GLWindow[ \n\tHelper: "+helper+", \n\tDrawable: "+drawable + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]"; @@ -483,8 +489,17 @@ public class GLWindow extends Window implements GLAutoDrawable { helper.removeGLEventListener(listener); } + public void setAnimator(Thread animator) { + helper.setAnimator(animator); + window.setPropagateRepaint(null==animator); + } + + public Thread getAnimator() { + return helper.getAnimator(); + } + public void invoke(boolean wait, GLRunnable glRunnable) { - helper.invoke(wait, glRunnable); + helper.invoke(this, wait, glRunnable); } public void display() { @@ -494,28 +509,26 @@ public class GLWindow extends Window implements GLAutoDrawable { public void display(boolean forceReshape) { if( null == window ) { return; } + if(sendDestroy || ( null!=window && window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) { + sendDestroy=false; + destroy(); + return; + } + if( null == context && window.isVisible() ) { // retry native window and drawable/context creation setVisible(true); } - if( window.isNativeWindowValid() && null != context ) { - if(runPumpMessages) { - window.getScreen().getDisplay().pumpMessages(); + if( window.isVisible() && window.isNativeWindowValid() && null != context ) { + if(forceReshape) { + sendReshape = true; } - if(sendDestroy || window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { - destroy(); - sendDestroy=false; - } else if ( window.isVisible() ) { - if(forceReshape) { - sendReshape = true; - } - windowLock(); - try{ - helper.invokeGL(drawable, context, displayAction, initAction); - } finally { - windowUnlock(); - } + windowLock(); + try{ + helper.invokeGL(drawable, context, displayAction, initAction); + } finally { + windowUnlock(); } } } @@ -546,7 +559,7 @@ public class GLWindow extends Window implements GLAutoDrawable { public void run() { // Lock: Locked Surface/Window by MakeCurrent/Release helper.init(GLWindow.this); - startTime = System.currentTimeMillis(); + startTime = System.currentTimeMillis(); // overwrite startTime to real init one curTime = startTime; if(perfLog) { lastCheck = startTime; @@ -560,10 +573,7 @@ public class GLWindow extends Window implements GLAutoDrawable { public void run() { // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release if (sendReshape) { - int width = getWidth(); - int height = getHeight(); - getGL().glViewport(0, 0, width, height); - helper.reshape(GLWindow.this, 0, 0, width, height); + helper.reshape(GLWindow.this, 0, 0, getWidth(), getHeight()); sendReshape = false; } @@ -589,8 +599,8 @@ public class GLWindow extends Window implements GLAutoDrawable { private DisplayAction displayAction = new DisplayAction(); public long getStartTime() { return startTime; } - public long getCurrentTime() { return curTime; } - public long getDuration() { return curTime-startTime; } + public long getCurrentTime() { curTime = System.currentTimeMillis(); return curTime; } + public long getDuration() { return getCurrentTime()-startTime; } public int getTotalFrames() { return totalFrames; } private long startTime = 0; diff --git a/src/newt/classes/com/jogamp/newt/util/Insets.java b/src/newt/classes/com/jogamp/newt/util/Insets.java new file mode 100644 index 000000000..068cc1dfb --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/util/Insets.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009 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.jogamp.newt.util; + +/** + * Simple class representing insets. + * + * @author tdv + */ +public class Insets implements Cloneable { + public int top; + public int left; + public int bottom; + public int right; + + /** + * Creates and initializes a new Insets object with the + * specified top, left, bottom, and right insets. + * @param top the inset from the top. + * @param left the inset from the left. + * @param bottom the inset from the bottom. + * @param right the inset from the right. + */ + public Insets(int top, int left, int bottom, int right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + + /** + * Checks whether two insets objects are equal. Two instances + * of Insets are equal if the four integer values + * of the fields top, left, + * bottom, and right are all equal. + * @return true if the two insets are equal; + * otherwise false. + */ + public boolean equals(Object obj) { + if (obj instanceof Insets) { + Insets insets = (Insets)obj; + return ((top == insets.top) && (left == insets.left) && + (bottom == insets.bottom) && (right == insets.right)); + } + return false; + } + + /** + * Returns the hash code for this Insets. + * + * @return a hash code for this Insets. + */ + public int hashCode() { + int sum1 = left + bottom; + int sum2 = right + top; + int val1 = sum1 * (sum1 + 1)/2 + left; + int val2 = sum2 * (sum2 + 1)/2 + top; + int sum3 = val1 + val2; + return sum3 * (sum3 + 1)/2 + val2; + } + + public String toString() { + return getClass().getName() + "[top=" + top + ",left=" + left + + ",bottom=" + bottom + ",right=" + right + "]"; + } + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new InternalError(); + } + } + +} -- cgit v1.2.3