diff options
author | Sven Gothel <[email protected]> | 2010-06-10 09:35:06 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2010-06-10 09:35:06 +0200 |
commit | 1d333a771ce0bc7c8594e21d031703f698f06a46 (patch) | |
tree | 933d470582896320855fa1d98c1a917edc412c24 /src/newt/classes | |
parent | 4512900ddcb9ce9a498411d257b1b6d6010ec006 (diff) |
Fix: Locking/Threading; Common IntIntHashMap and Buffers; Fix: glMap*Buffer*; GLX/WGL/CgGL: All runtime dynamic; Misc ..
TODO: Compile and test on MacOSX ..
Fix:
=====
Multithreading/Locking:
See jogl/doc/Implementation/MultiThreading.txt
- Locking layer is not platform agnostic, ie GLContextImpl, GLDrawableImpl, ..
and NEWT: Window/Display
- No more use of JAWT global lock necessary, removed.
- No need for X11 Display lock, on the contrary,
this made the NV driver hang.
- Use common window/surface lock
- All NativeWindow surfaceLock's are recursive now
glMapBuffer: If size is 0, don't do cont with the native call.
glMapBufferRange: Fix capacity.
glNamedBufferDataEXT: Track the size.
glMapNamedBufferEXT: Manual impl. - use the tracked size
glXGetVisualFromFBConfig, glXChooseFBConfig, glXChooseVisual: Instead of
ignoring and implement a renamed version (*Copied), we just use ManualImplementation
for the proper copy-result code.
DesktopGLDynamicLookupHelper: Initialize _hasGLBinding* attributes
in the determing loadGLJNILibrary() method, which is called by super().
Otherwise static init will overwrite them after the super() call.
X11GLXDrawableFactory: Don't release anything at shutdown (removed sharedContext.destroy()),
since this caused a freeze/SEGV sometimes.
Fixed NEWT's reparentWindow() functionality incl NewtCanvasAWT usage.
- Native: if not visible, don't focus, etc
- NewtCanvasAWT: Use the container size to start with
- Run the command on the EDT
Using GlueGen's new DynamicLibraryBundle utility:
- X11, Windows and MacOSX OpenGL adapted to DynamicLibraryBundleInfo.
- X11GLXDynamicLookupHelper -> X11GLXDynamicLibraryBundleInfo
- Remove all path from lib names.
- GL order: libGL.so.1, libGL.so, GL
- shallLinkGlobal: true -> to server some 'old' DRI systems
-> http://dri.sourceforge.net/doc/DRIuserguide.html
- shallLookupGlobal: false
- Try both : glXGetProcAddressARB and glXGetProcAddress
- Using bootstrap: GLX.glXGetProcAddress(long glxGetProcAddressHandle, String glFuncName)
Found the issue with LIBGL_DRIVERS_PATH, ie if not set
no valid GL instance can be found (ie ATI fglrx/DRI).
This may happen if using a differen user than the desktop user
for whom the env var is set within some /etc/X11/Xsession.d/ script.
Enhancements:
=============
GLBufferSizeTracker: Use IntIntHashMap and add DirectState size tracking.
GLBufferStateTracker: Use IntIntHashMap.
GLStateTracker: Use IntIntHashMap.
GLDynamicLookupHelper: More generic (global loading/lookup and GetProcAddress function name list),
remove redundant code.
FIXME:
MacOSXCGLDynamicLookupHelper:
- Not tested
- Not using NSImage lookup anymore as recommended by OSX API Doc,
so dlsym is used always (to be tested)
WindowsWGLDynamicLookupHelper:
- Not tested
GLX/WGL/CgGL is all runtime-dynamic as now, ie loaded and looked-up at runtime,
no compile time dependencies to GL anymore, nor a need to specify CgGL.
Split up WGL in GDI and WGL, to allow proper dynamic runtime linkage of OpenGL32
while using static binding to GDI32
NEWT events generated by native code are enqueued and not send directly.
This should ease locking mechanisms .. if any are necessary.
NEWT: More platform specific code moved to *Impl method,
simplifying the generic code of the superclass and impl protocol.
Cleanup:
=========
Replace all InternalBufferUtil's with com.jogamp.common.nio.Buffers
Removed all InternalBufferUtil's from repository
Removed GLContextImpl notion of 'optimized' surface locking,
where the surface gets unlocked during makeCurrent/release.
This just makes no sense and would impact multithreading in a horrible way.
Diffstat (limited to 'src/newt/classes')
13 files changed, 410 insertions, 339 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 8710f82ba..c804b3d2d 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -33,8 +33,9 @@ package com.jogamp.newt; -import com.jogamp.newt.event.*; import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; +import com.jogamp.newt.event.*; import com.jogamp.newt.impl.Debug; import com.jogamp.newt.util.EDTUtil; import java.util.*; @@ -112,7 +113,7 @@ public abstract class Display { Map displayMap = getCurrentDisplayMap(); Set entrySet = displayMap.entrySet(); Iterator i = entrySet.iterator(); - System.err.println(prefix+" DisplayMap[] entries: "+entrySet.size()+" - "+Thread.currentThread()); + System.err.println(prefix+" DisplayMap[] entries: "+entrySet.size()+" - "+getThreadName()); for(int j=0; i.hasNext(); j++) { Map.Entry entry = (Map.Entry) i.next(); System.err.println(" ["+j+"] "+entry.getKey()+" -> "+entry.getValue()); @@ -142,12 +143,12 @@ public abstract class Display { display.type=type; display.refCount=0; if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") NEW: refCount "+display.refCount+", "+display+" "+Thread.currentThread()); + System.err.println("Display.create("+getFQName(type, name)+") NEW: refCount "+display.refCount+", "+display+" "+getThreadName()); } } else { tmpDisplay = null; if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") REUSE: refCount "+display.refCount+", "+display+" "+Thread.currentThread()); + System.err.println("Display.create("+getFQName(type, name)+") REUSE: refCount "+display.refCount+", "+display+" "+getThreadName()); } } synchronized(display) { @@ -163,7 +164,7 @@ public abstract class Display { } setCurrentDisplay(display); if(DEBUG) { - System.err.println("Display.create("+getFQName(type, name)+") CreateNative: "+display+" "+Thread.currentThread()); + System.err.println("Display.create("+getFQName(type, name)+") CreateNative: "+display+" "+getThreadName()); } } } @@ -192,7 +193,7 @@ public abstract class Display { new Runnable() { public void run() { if(null!=f_dpy.getGraphicsDevice()) { - f_dpy.pumpMessagesImpl(); + f_dpy.dispatchMessages(); } } } ); edt = edtUtil.start(); } @@ -220,7 +221,7 @@ public abstract class Display { if(0==refCount) { removeCurrentDisplay(type, name); if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") REMOVE: "+this+" "+Thread.currentThread()); + System.err.println("Display.destroy("+getFQName()+") REMOVE: "+this+" "+getThreadName()); } final Display f_dpy = this; final EDTUtil f_edt = edtUtil; @@ -240,7 +241,7 @@ public abstract class Display { aDevice = null; } else { if(DEBUG) { - System.err.println("Display.destroy("+getFQName()+") KEEP: refCount "+refCount+", "+this+" "+Thread.currentThread()); + System.err.println("Display.destroy("+getFQName()+") KEEP: refCount "+refCount+", "+this+" "+getThreadName()); } } if(DEBUG) { @@ -267,7 +268,7 @@ public abstract class Display { protected String validateDisplayName(String name, long handle) { if(null==name && 0!=handle) { - name="wrapping-0x"+Long.toHexString(handle); + name="wrapping-"+toHexString(handle); } return ( null == name ) ? nilString : name ; } @@ -290,11 +291,6 @@ public abstract class Display { } public synchronized void pumpMessages() { - pumpMessagesImpl(); - } - - private void pumpMessagesImpl() { - if(0==refCount) return; dispatchMessages(); } @@ -302,27 +298,73 @@ public abstract class Display { return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", "+aDevice+"]"; } + public static String getThreadName() { + return Thread.currentThread().getName(); + } + + public static String toHexString(int hex) { + return "0x" + Integer.toHexString(hex); + } + + public static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } + + protected abstract void dispatchMessagesNative(); + private Object eventsLock = new Object(); private LinkedList/*<NEWTEvent>*/ events = new LinkedList(); + private boolean events2Wait = false; protected void dispatchMessages() { + if(0==refCount) return; // we should not exist .. + if(!events.isEmpty()) { - synchronized(events) { - while (!events.isEmpty()) { - NEWTEvent e = (NEWTEvent) events.removeFirst(); - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + if(events2Wait) { + synchronized(eventsLock) { + while (!events.isEmpty()) { + NEWTEvent e = (NEWTEvent) events.removeFirst(); + Object source = e.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(e); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + } + } + events2Wait = false; // clear + eventsLock.notifyAll(); + } + } else { + // swap events list to free ASAP + LinkedList/*<NEWTEvent>*/ _events = null; + synchronized(eventsLock) { + if(!events.isEmpty()) { + _events = events; + events = new LinkedList(); + } + eventsLock.notifyAll(); + } + if( null != _events ) { + while (!_events.isEmpty()) { + NEWTEvent e = (NEWTEvent) _events.removeFirst(); + Object source = e.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(e); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + } } } - events.notifyAll(); } } - dispatchMessagesNative(); + // lock(); + try { + dispatchMessagesNative(); + } finally { + // unlock(); + } } public void enqueueEvent(NEWTEvent e) { @@ -330,17 +372,18 @@ public abstract class Display { } public void enqueueEvent(boolean wait, NEWTEvent e) { - synchronized(events) { + synchronized(eventsLock) { if(DEBUG) { System.out.println("Display.enqueueEvent: START - wait "+wait+", "+e); } + events2Wait = wait; events.addLast(e); } if(wait && !events.isEmpty()) { - synchronized(events) { + synchronized(eventsLock) { while(!events.isEmpty()) { try { - events.wait(); + eventsLock.wait(); } catch (InterruptedException ie) { ie.printStackTrace(); } @@ -352,12 +395,13 @@ public abstract class Display { } } + public void lock() { + aDevice.lock(); + } - /** Default impl. nop - Currently only X11 needs a Display lock */ - protected void lockDisplay() { } - - /** Default impl. nop - Currently only X11 needs a Display lock */ - protected void unlockDisplay() { } + public void unlock() { + aDevice.unlock(); + } protected EDTUtil edtUtil = null; protected Thread edt = null; diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 87f0bf0eb..89c1bd146 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -132,14 +132,6 @@ public abstract class Window implements NativeWindow } } - public static String toHexString(int hex) { - return "0x" + Integer.toHexString(hex); - } - - public static String toHexString(long hex) { - return "0x" + Long.toHexString(hex); - } - protected Screen screen; protected NativeWindow parentNativeWindow; @@ -162,14 +154,15 @@ public abstract class Window implements NativeWindow return 0 != windowHandle ; } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.createNative() START ("+Thread.currentThread()+", "+this+")"); + System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")"); } if(validateParentWindowHandle()) { + Display dpy = getScreen().getDisplay(); createNativeImpl(); setVisibleImpl(true); } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.createNative() END ("+Thread.currentThread()+", "+this+")"); + System.err.println("Window.createNative() END ("+getThreadName()+", "+this+")"); } return 0 != windowHandle ; } @@ -185,26 +178,27 @@ public abstract class Window implements NativeWindow private static long getNativeWindowHandle(NativeWindow nativeWindow) { long handle = 0; if(null!=nativeWindow) { - boolean ok = true; + boolean locked=false; try { - nativeWindow.lockSurface(); + if( NativeWindow.LOCK_SURFACE_NOT_READY < nativeWindow.lockSurface() ) { + locked=true; + handle = nativeWindow.getWindowHandle(); + if(0==handle) { + throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+nativeWindow); + } + } } catch (NativeWindowException nwe) { - // parent native window not ready .. just skip action for now - ok = false; if(DEBUG_IMPLEMENTATION) { System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe); } - } - if(ok) { - handle = nativeWindow.getWindowHandle(); - nativeWindow.unlockSurface(); - if(0==handle) { - throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+nativeWindow); - } - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.getNativeWindowHandle: "+nativeWindow); + } finally { + if(locked) { + nativeWindow.unlockSurface(); } } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.getNativeWindowHandle: locked "+locked+", "+nativeWindow); + } } return handle; } @@ -281,7 +275,11 @@ public abstract class Window implements NativeWindow title = ""; } this.title = title; + if(0 != windowHandle) { + setTitleImpl(title); + } } + protected void setTitleImpl(String title) {} public void setUndecorated(boolean value) { undecorated = value; @@ -296,7 +294,11 @@ public abstract class Window implements NativeWindow } public void requestFocus() { + if(0 != windowHandle) { + requestFocusImpl(); + } } + protected void requestFocusImpl() {} // // NativeWindow impl @@ -306,35 +308,35 @@ public abstract class Window implements NativeWindow public int lockSurface() { // We leave the ToolkitLock lock to the specializtion's discretion, // ie the implicit JAWTWindow in case of AWTWindow - if(isDestroyed() || !isNativeWindowValid()) { - return LOCK_SURFACE_NOT_READY; - } - surfaceLock.lock(); - screen.getDisplay().lockDisplay(); + + windowLock.lock(); + + // if(windowLock.getRecursionCount() == 0) { // allow recursion to lock again, always + if(isDestroyed() || !isNativeWindowValid()) { + windowLock.unlock(); + return LOCK_SURFACE_NOT_READY; + } + // } return LOCK_SUCCESS; } /** Recursive and unblocking unlockSurface() implementation */ public void unlockSurface() throws NativeWindowException { - surfaceLock.unlock( new Runnable() { - public void run() { - screen.getDisplay().unlockDisplay(); - } - } ); + windowLock.unlock(); // We leave the ToolkitLock unlock to the specializtion's discretion, // ie the implicit JAWTWindow in case of AWTWindow } public boolean isSurfaceLocked() { - return surfaceLock.isLocked(); + return windowLock.isLocked(); } public Thread getSurfaceLockOwner() { - return surfaceLock.getOwner(); + return windowLock.getOwner(); } public Exception getLockedStack() { - return surfaceLock.getLockedStack(); + return windowLock.getLockedStack(); } /** @@ -352,6 +354,19 @@ public abstract class Window implements NativeWindow destroy(false); } + /** + * @param deep If true, all resources, ie listeners, parent handles, size, position + * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #destroy() + * @see #invalidate(boolean) + */ + public void destroy(boolean deep) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new DestroyAction(deep)); + } + } + class DestroyAction implements Runnable { boolean deep; public DestroyAction(boolean deep) { @@ -361,7 +376,7 @@ public abstract class Window implements NativeWindow windowLock(); try { if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.destroy(deep: "+deep+") START "+Thread.currentThread()+", "+this); + System.err.println("Window.destroy(deep: "+deep+") START "+getThreadName()+", "+this); } // Childs first .. @@ -397,22 +412,23 @@ public abstract class Window implements NativeWindow } } Display dpy = null; + Screen scr = null; if( null != screen && 0 != windowHandle ) { - Screen scr = screen; - dpy = (null!=screen) ? screen.getDisplay() : null; + scr = screen; + dpy = screen.getDisplay(); closeNative(); } invalidate(deep); if(deep) { - if(null!=screen) { - screen.destroy(); + if(null!=scr) { + scr.destroy(); } if(null!=dpy) { dpy.destroy(); } } if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.destroy(deep: "+deep+") END "+Thread.currentThread()+", "+this); + System.err.println("Window.destroy(deep: "+deep+") END "+getThreadName()+", "+this); } } finally { windowUnlock(); @@ -421,19 +437,6 @@ public abstract class Window implements NativeWindow } /** - * @param deep If true, all resources, ie listeners, parent handles, size, position - * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call - * this method with deep = true, you will not be able to regenerate the Window. - * @see #destroy() - * @see #invalidate(boolean) - */ - public void destroy(boolean deep) { - if(!isDestroyed()) { - runOnEDTIfAvail(true, new DestroyAction(deep)); - } - } - - /** * <p> * render all native window information invalid, * as if the native window was destroyed.<br></p> @@ -461,7 +464,7 @@ public abstract class Window implements NativeWindow windowLock(); try{ if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - String msg = new String("!!! Window Invalidate(deep: "+deep+") "+Thread.currentThread()); + String msg = new String("!!! Window Invalidate(deep: "+deep+") "+getThreadName()); System.err.println(msg); //Exception e = new Exception(msg); //e.printStackTrace(); @@ -600,23 +603,23 @@ public abstract class Window implements NativeWindow protected void windowDestroyNotify() { if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyNotify START "+Thread.currentThread()); + System.err.println("Window.windowDestroyNotify START "+getThreadName()); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); if(handleDestroyNotify && !isDestroyed()) { destroy(); } if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyeNotify END "+Thread.currentThread()); + System.err.println("Window.windowDestroyeNotify END "+getThreadName()); } } protected void windowDestroyed() { if(DEBUG_WINDOW_EVENT) { - System.err.println("Window.windowDestroyed "+Thread.currentThread()); + System.err.println("Window.windowDestroyed "+getThreadName()); } invalidate(); } @@ -626,6 +629,68 @@ public abstract class Window implements NativeWindow return false; } + class ReparentAction implements Runnable { + NativeWindow newParent; + Screen newScreen; + public ReparentAction(NativeWindow newParent, Screen newScreen) { + this.newParent = newParent; + this.newScreen = newScreen; + } + public void run() { + windowLock(); + try{ + if ( 0 == windowHandle && null != newScreen ) { + screen = newScreen; + } + long newParentHandle = 0 ; + if(null!=newParent) { + newParentHandle = getNativeWindowHandle(newParent); + if ( 0 == newParentHandle ) { + return; // bail out .. not ready yet + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); + } + + if(null!=parentNativeWindow && parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().removeChild(Window.this); + } + parentNativeWindow = newParent; + if(parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().addChild(Window.this); + } + + if(newParentHandle != parentWindowHandle) { + parentWindowHandle = newParentHandle; + if(0!=parentWindowHandle) { + // reset position to 0/0 within parent space + // FIXME .. cache position ? + x = 0; + y = 0; + } + boolean reparentRes = false; + reparentRes = reparentWindowImpl(); + if(!reparentRes) { + parentWindowHandle = 0; + + // do it the hard way .. reconstruction with setVisible(true) + if( 0 != windowHandle ) { + destroy(false); + } + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparentWindow: END ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + } + } finally { + windowUnlock(); + } + } + } + /** * Change this window's parent window.<br> * <P> @@ -639,54 +704,11 @@ public abstract class Window implements NativeWindow * this Screen is being used. */ public void reparentWindow(NativeWindow newParent, Screen newScreen) { - windowLock(); - try{ - if ( 0 == windowHandle && null != newScreen ) { - screen = newScreen; - } - long newParentHandle = 0 ; - if(null!=newParent) { - newParentHandle = getNativeWindowHandle(newParent); - if ( 0 == newParentHandle ) { - return; // bail out .. not ready yet - } - } - - if(DEBUG_IMPLEMENTATION) { - System.err.println("reparent: START ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); - } - - if(null!=parentNativeWindow && parentNativeWindow instanceof Window) { - ((Window)parentNativeWindow).getInnerWindow().removeChild(this); - } - parentNativeWindow = newParent; - if(parentNativeWindow instanceof Window) { - ((Window)parentNativeWindow).getInnerWindow().addChild(this); - } - - if(newParentHandle != parentWindowHandle) { - parentWindowHandle = newParentHandle; - if(0!=parentWindowHandle) { - // reset position to 0/0 within parent space - // FIXME .. cache position ? - x = 0; - y = 0; - } - if(!reparentWindowImpl()) { - parentWindowHandle = 0; - - // do it the hard way .. reconstruction with setVisible(true) - if( 0 != windowHandle ) { - destroy(false); - } - } - } - - if(DEBUG_IMPLEMENTATION) { - System.err.println("reparentWindow: END ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + if(!isDestroyed()) { + runOnEDTIfAvail(true, new ReparentAction(newParent, newScreen)); + if( isVisible() ) { + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener } - } finally { - windowUnlock(); } } @@ -733,7 +755,7 @@ public abstract class Window implements NativeWindow } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setVisible: END ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); + System.err.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); } } finally { windowUnlock(); @@ -768,7 +790,7 @@ public abstract class Window implements NativeWindow */ public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { - String msg = new String("Window setVisible: START ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + 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); Exception ee = new Exception(msg); ee.printStackTrace(); @@ -1000,49 +1022,19 @@ public abstract class Window implements NativeWindow // // MouseListener/Event Support // - - public void addMouseListener(MouseListener l) { - if(l == null) { - return; - } - synchronized(mouseListeners) { - ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); - newMouseListeners.add(l); - mouseListeners = newMouseListeners; - } - } - - public void removeMouseListener(MouseListener l) { - if (l == null) { - return; - } - synchronized(mouseListeners) { - ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); - newMouseListeners.remove(l); - mouseListeners = newMouseListeners; - } - } - - public MouseListener[] getMouseListeners() { - synchronized(mouseListeners) { - return (MouseListener[]) mouseListeners.toArray(); - } - } - private ArrayList mouseListeners = new ArrayList(); private int mouseButtonPressed = 0; // current pressed mouse button number private long lastMousePressed = 0; // last time when a mouse button was pressed private int lastMouseClickCount = 0; // last mouse button click count public static final int ClickTimeout = 300; - /** Be aware that this method synthesizes the events: MouseClicked and MouseDragged */ - protected void sendMouseEvent(int eventType, int modifiers, + protected void enqueueMouseEvent(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("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + System.err.println("enqueueMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { @@ -1086,12 +1078,41 @@ public abstract class Window implements NativeWindow } else { e = new MouseEvent(eventType, this, when, modifiers, x, y, 0, button, 0); } - sendMouseEvent(e); + screen.getDisplay().enqueueEvent(e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.err.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); + System.err.println("enqueueMouseEvent: synthesized MOUSE_CLICKED event"); } - sendMouseEvent(eClicked); + screen.getDisplay().enqueueEvent(eClicked); + } + } + + + public void addMouseListener(MouseListener l) { + if(l == null) { + return; + } + synchronized(mouseListeners) { + ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); + newMouseListeners.add(l); + mouseListeners = newMouseListeners; + } + } + + public void removeMouseListener(MouseListener l) { + if (l == null) { + return; + } + synchronized(mouseListeners) { + ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); + newMouseListeners.remove(l); + mouseListeners = newMouseListeners; + } + } + + public MouseListener[] getMouseListeners() { + synchronized(mouseListeners) { + return (MouseListener[]) mouseListeners.toArray(); } } @@ -1141,6 +1162,12 @@ public abstract class Window implements NativeWindow // KeyListener/Event Support // + protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + screen.getDisplay().enqueueEvent( + new KeyEvent(eventType, this, System.currentTimeMillis(), + modifiers, keyCode, keyChar) ); + } + public void addKeyListener(KeyListener l) { if(l == null) { return; @@ -1171,11 +1198,6 @@ public abstract class Window implements NativeWindow private ArrayList keyListeners = new ArrayList(); - protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - sendKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), - modifiers, keyCode, keyChar) ); - } - protected void sendKeyEvent(KeyEvent e) { if(DEBUG_KEY_EVENT) { System.err.println("sendKeyEvent: "+e); @@ -1205,6 +1227,11 @@ public abstract class Window implements NativeWindow // // WindowListener/Event Support // + protected void enqueueWindowEvent(int eventType) { + WindowEvent event = new WindowEvent(eventType, this, System.currentTimeMillis()); + screen.getDisplay().enqueueEvent( event ); + // sendWindowEvent ( event ); // FIXME: Think about performance/lag .. ? + } private ArrayList windowListeners = new ArrayList(); @@ -1236,10 +1263,6 @@ public abstract class Window implements NativeWindow } } - protected void sendWindowEvent(int eventType) { - sendWindowEvent( new WindowEvent(eventType, this, System.currentTimeMillis()) ); - } - protected void sendWindowEvent(WindowEvent e) { if(DEBUG_WINDOW_EVENT) { System.err.println("sendWindowEvent: "+e); @@ -1365,8 +1388,7 @@ public abstract class Window implements NativeWindow return sb.toString(); } - private RecursiveToolkitLock surfaceLock = new RecursiveToolkitLock(); - private RecursiveToolkitLock windowLock = new RecursiveToolkitLock(); + protected RecursiveToolkitLock windowLock = new RecursiveToolkitLock(); private static final boolean TRACE_LOCK = false; @@ -1387,8 +1409,23 @@ public abstract class Window implements NativeWindow protected final boolean windowIsLocked() { return getInnerWindow().windowLock.isLocked(); } + protected RecursiveToolkitLock getWindowLock() { + return getInnerWindow().windowLock; + } protected final void shouldNotCallThis() { throw new NativeWindowException("Should not call this"); } + + public static String getThreadName() { + return Display.getThreadName(); + } + + public static String toHexString(int hex) { + return Display.toHexString(hex); + } + + public static String toHexString(long hex) { + return Display.toHexString(hex); + } } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 23269a93b..a84e571e4 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -55,7 +55,6 @@ public class NewtCanvasAWT extends java.awt.Canvas { /** * Instantiates a NewtCanvas without a NEWT child.<br> - * @see #setNEWTChild(Window) */ public NewtCanvasAWT() { super(); @@ -74,8 +73,9 @@ public class NewtCanvasAWT extends java.awt.Canvas { if(newtChild!=child) { newtChild = child; if(null!=parent) { + java.awt.Container cont = getContainer(this); // reparent right away, addNotify has been called already - reparentWindow( (null!=newtChild) ? true : false ); + reparentWindow( (null!=newtChild) ? true : false, cont ); } } return this; @@ -100,26 +100,38 @@ public class NewtCanvasAWT extends java.awt.Canvas { } } + static java.awt.Container getContainer(java.awt.Component comp) { + while( null != comp && !(comp instanceof java.awt.Container) ) { + comp = comp.getParent(); + } + if(comp instanceof java.awt.Container) { + return (java.awt.Container) comp; + } + return null; + } + public void addNotify() { super.addNotify(); disableBackgroundErase(); + 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()); + System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()+" -> "+cont); } - reparentWindow(true); + reparentWindow(true, cont); } public void removeNotify() { + java.awt.Container cont = getContainer(this); if(DEBUG_IMPLEMENTATION) { - System.err.println("NewtCanvasAWT.removeNotify: "+newtChild); + System.err.println("NewtCanvasAWT.removeNotify: "+newtChild+", from "+cont); } - reparentWindow(false); + reparentWindow(false, cont); super.removeNotify(); } - void reparentWindow(boolean add) { + void reparentWindow(boolean add, java.awt.Container cont) { if(null==newtChild) { return; // nop } @@ -129,20 +141,18 @@ public class NewtCanvasAWT extends java.awt.Canvas { parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); } if(null!=parent) { - // 1st choice - NEWT size := AWT size - // 2nd choice - AWT size := NEWT size - if(0>=getWidth()*getHeight()) { - setSize(newtChild.getWidth(), newtChild.getHeight()); // #2 + if(DEBUG_IMPLEMENTATION) { + System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); } + setSize(cont.getWidth(), cont.getHeight()); + newtChild.setSize(cont.getWidth(), cont.getHeight()); + Screen screen = null; if( !newtChild.isNativeWindowValid() ) { screen = NewtFactoryAWT.createCompatibleScreen(parent); } newtChild.reparentWindow(parent, screen); - if ( 0 < getWidth() * getHeight() ) { - newtChild.setSize(getWidth(), getHeight()); // #1 - newtChild.setVisible(true); - } + newtChild.setVisible(true); setWindowAdapter(true); } } else { 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 33c291e96..7905a728c 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -57,6 +57,9 @@ public class AWTParentWindowAdapter // Need to resize the NEWT child window // the resized event will be send via the native window feedback. final java.awt.Component comp = e.getComponent(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT: componentResized: "+comp); + } newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { if( 0 < comp.getWidth() * comp.getHeight() ) { @@ -87,7 +90,7 @@ public class AWTParentWindowAdapter if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) { final boolean showing = changed.isShowing(); if(DEBUG_IMPLEMENTATION) { - System.out.println("hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); + System.out.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } if(!newtWindow.isDestroyed()) { newtWindow.runOnEDTIfAvail(false, new Runnable() { @@ -100,7 +103,7 @@ public class AWTParentWindowAdapter if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) { final boolean displayability = changed.isDisplayable(); if(DEBUG_IMPLEMENTATION) { - System.out.println("hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed); + System.out.println("AWT: hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed); } } } 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 570b0678a..ee7ca97ad 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -105,6 +105,10 @@ public class AWTWindowAdapter } public void componentShown(java.awt.event.ComponentEvent e) { + final java.awt.Component comp = e.getComponent(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT: componentShown: "+comp); + } /** if(null==newtListener) { if(!newtWindow.isDestroyed()) { @@ -118,6 +122,10 @@ public class AWTWindowAdapter } public void componentHidden(java.awt.event.ComponentEvent e) { + final java.awt.Component comp = e.getComponent(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("AWT: componentHidden: "+comp); + } /** if(null==newtListener) { if(!newtWindow.isDestroyed()) { 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 f97625320..a06b7160c 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -84,8 +84,7 @@ public class AWTWindow extends Window { // non fullscreen dimensions .. private int nfs_width, nfs_height, nfs_x, nfs_y; - public void setTitle(final String title) { - super.setTitle(title); + protected void setTitleImpl(final String title) { runOnEDT(true, new Runnable() { public void run() { if (frame != null) { @@ -265,17 +264,17 @@ public class AWTWindow extends Window { return canvas; } - protected void sendWindowEvent(int eventType) { - super.sendWindowEvent(eventType); + protected void enqueueWindowEvent(int eventType) { + super.enqueueWindowEvent(eventType); } - protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - super.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + super.enqueueKeyEvent(eventType, modifiers, keyCode, keyChar); } - protected void sendMouseEvent(int eventType, int modifiers, + protected void enqueueMouseEvent(int eventType, int modifiers, int x, int y, int button, int rotation) { - super.sendMouseEvent(eventType, modifiers, x, y, button, rotation); + super.enqueueMouseEvent(eventType, modifiers, x, y, button, rotation); } private void runOnEDT(boolean wait, Runnable r) { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 74cb53f7e..1b8a62a9c 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -116,7 +116,7 @@ public class Window extends com.jogamp.newt.Window { return fullscreen; } - public void requestFocus() { + protected void requestFocusImpl() { ((Display)screen.getDisplay()).setFocus(this); } 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 b6328b02f..8a656a5a8 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -231,8 +231,8 @@ public class MacWindow extends Window { } } - public void setTitle(String title) { - super.setTitle(title); + protected void setTitleImpl(final String title) { + // FIXME: move nsViewLock up to window lock nsViewLock.lock(); try { if (windowHandle != 0) { @@ -243,8 +243,8 @@ public class MacWindow extends Window { } } - public void requestFocus() { - super.requestFocus(); + protected void requestFocusImpl() { + // FIXME: move nsViewLock up to window lock nsViewLock.lock(); try { if (windowHandle != 0) { @@ -309,7 +309,7 @@ public class MacWindow extends Window { if (DEBUG_IMPLEMENTATION) { System.out.println(" Posted WINDOW_RESIZED event"); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } } @@ -340,15 +340,15 @@ public class MacWindow extends Window { if (DEBUG_IMPLEMENTATION) { System.out.println(" Posted WINDOW_MOVED event"); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } } private void focusChanged(boolean focusGained) { if (focusGained) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); } else { - sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); } } @@ -435,12 +435,12 @@ public class MacWindow extends Window { return keyChar; } - protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + protected void enqueueKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { int key = convertKeyChar(keyChar); - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()); + 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.sendKeyEvent(eventType, modifiers, key, keyChar); + super.enqueueKeyEvent(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 +482,9 @@ public class MacWindow extends Window { ie.printStackTrace(); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); - sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(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 54623996c..0d12a4a0a 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 @@ -135,7 +135,7 @@ public class KDWindow extends Window { } else { ((KDScreen)screen).setScreenSize(width, height); } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } 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 5e1b5a43c..aedb4ed7d 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -53,35 +53,21 @@ public class WindowsWindow extends Window { public WindowsWindow() { } - Thread hdcOwner = null; - - public synchronized int lockSurface() throws NativeWindowException { + public int lockSurface() throws NativeWindowException { int res = super.lockSurface(); - if(LOCK_SUCCESS==res && 0!=windowHandle) { - if(hdc!=0) { - throw new NativeWindowException("NEWT Surface handle set HDC "+toHexString(hdc)+" - "+Thread.currentThread().getName()+" ; "+this); - } + if( LOCK_SUCCESS == res && 0 != windowHandle && 0 == hdc ) { hdc = GetDC0(windowHandle); hmon = MonitorFromWindow0(windowHandle); - hdcOwner = Thread.currentThread(); } return res; } - public synchronized void unlockSurface() { - // prevalidate, before we change data .. - Thread cur = Thread.currentThread(); - if ( getSurfaceLockOwner() != cur ) { - getLockedStack().printStackTrace(); - throw new NativeWindowException(cur+": Not owner, owner is "+getSurfaceLockOwner()); - } - if (0!=hdc && 0!=windowHandle) { - if(hdcOwner != cur) { - throw new NativeWindowException("NEWT Surface handle set HDC "+toHexString(hdc)+" by other thread "+hdcOwner+", this "+cur+" ; "+this); - } + public void unlockSurface() { + getWindowLock().validateLocked(); + + if ( 0 != hdc && 0 != windowHandle && getWindowLock().getRecursionCount() == 0) { ReleaseDC0(windowHandle, hdc); hdc=0; - hdcOwner=null; } super.unlockSurface(); } @@ -187,23 +173,14 @@ public class WindowsWindow extends Window { return true; } - // @Override - public void requestFocus() { - super.requestFocus(); + protected void requestFocusImpl() { if (windowHandle != 0L) { - requestFocus0(windowHandle); + requestFocus0(fullscreen?0:parentWindowHandle, windowHandle); } } - // @Override - public void setTitle(String title) { - if (title == null) { - title = ""; - } - if (0!=windowHandle && !title.equals(getTitle())) { - super.setTitle(title); - setTitle0(windowHandle, title); - } + protected void setTitleImpl(final String title) { + setTitle0(windowHandle, title); } public Insets getInsets() { @@ -229,7 +206,7 @@ public class WindowsWindow extends Window { private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private native void reparentWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private static native void setTitle0(long windowHandle, String title); - private static native void requestFocus0(long windowHandle); + private static native void requestFocus0(long parentWindowHandle, long windowHandle); private void insetsChanged(int left, int top, int right, int bottom) { if (left != -1 && top != -1 && right != -1 && bottom != -1) { @@ -248,7 +225,7 @@ public class WindowsWindow extends Window { nfs_width=width; nfs_height=height; } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } } @@ -260,7 +237,7 @@ public class WindowsWindow extends Window { nfs_x=x; nfs_y=y; } - sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } } @@ -272,9 +249,9 @@ public class WindowsWindow extends Window { */ private void focusChanged(long focusOwner, boolean focusGained) { if (focusGained) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); } else { - sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); } } } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 54fe0542b..6701d6c8e 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -40,6 +40,7 @@ import com.jogamp.newt.impl.*; import com.jogamp.nativewindow.impl.x11.X11Util; public class X11Display extends Display { + static { NEWTJNILibLoader.loadNEWT(); @@ -65,7 +66,7 @@ public class X11Display extends Display { } protected void createNative() { - long handle= X11Util.createThreadLocalDisplay(name); + long handle = X11Util.createThreadLocalDisplay(name); if( 0 == handle ) { throw new RuntimeException("Error creating display: "+name); } @@ -89,16 +90,6 @@ public class X11Display extends Display { DispatchMessages0(getHandle(), javaObjectAtom, windowDeleteAtom); } - protected void lockDisplay() { - super.lockDisplay(); - X11Util.XLockDisplay(getHandle()); - } - - protected void unlockDisplay() { - X11Util.XUnlockDisplay(getHandle()); - super.unlockDisplay(); - } - protected long getJavaObjectAtom() { return javaObjectAtom; } protected long getWindowDeleteAtom() { return windowDeleteAtom; } 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 a51eee241..e7fc96019 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -58,21 +58,20 @@ public class X11Window extends Window { X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; long visualID = x11config.getVisualID(); long w = CreateWindow0(parentWindowHandle, - display.getHandle(), screen.getIndex(), visualID, - display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, isUndecorated()); + display.getHandle(), screen.getIndex(), visualID, + display.getJavaObjectAtom(), display.getWindowDeleteAtom(), + x, y, width, height, isUndecorated()); if (w == 0 || w!=windowHandle) { throw new NativeWindowException("Error creating window: "+w); } windowHandleClose = windowHandle; - displayHandleClose = display.getHandle(); } protected void closeNative() { - if(0!=displayHandleClose && 0!=windowHandleClose && null!=getScreen() ) { + if(0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); try { - CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); + CloseWindow0(display.getHandle(), windowHandleClose, display.getJavaObjectAtom()); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); @@ -80,14 +79,12 @@ public class X11Window extends Window { } } finally { windowHandleClose = 0; - displayHandleClose = 0; } } } protected void windowDestroyed() { windowHandleClose = 0; - displayHandleClose = 0; super.windowDestroyed(); } @@ -101,41 +98,31 @@ public class X11Window extends Window { } protected void setPositionImpl(int x, int y) { - // this x/y will be set by windowChanged, called by X11 setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); } protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { - setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, isUndecorated(fullscreen)); + setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, + x, y, w, h, isUndecorated(fullscreen), isVisible()); return fullscreen; } protected boolean reparentWindowImpl() { if(0!=windowHandle) { - reparentWindow0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, isUndecorated()); - // X11 reparent unmaps the window - setVisibleImpl(visible); + reparentWindow0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, + x, y, isUndecorated(), isVisible()); } return true; } - // @Override - public void requestFocus() { - super.requestFocus(); + protected void requestFocusImpl() { if (windowHandle != 0L) { requestFocus0(getDisplayHandle(), windowHandle); } } - // @Override - public void setTitle(String title) { - if (title == null) { - title = ""; - } - if (0!=windowHandle && !title.equals(getTitle())) { - super.setTitle(title); - setTitle0(getDisplayHandle(), windowHandle, title); - } + protected void setTitleImpl(String title) { + setTitle0(getDisplayHandle(), windowHandle, title); } @@ -151,12 +138,12 @@ public class X11Window extends Window { 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, - int x, int y, int width, int height, boolean undecorated); + int x, int y, int width, int height, boolean undecorated, boolean isVisible); private native void setTitle0(long display, long windowHandle, String title); private native void requestFocus0(long display, long windowHandle); private native void setPosition0(long parentWindowHandle, long display, long windowHandle, int x, int y); private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, - int x, int y, boolean undecorated); + int x, int y, boolean undecorated, boolean isVisible); private void windowChanged(int newX, int newY, int newWidth, int newHeight) { if(width != newWidth || height != newHeight) { @@ -169,7 +156,7 @@ public class X11Window extends Window { nfs_width=width; nfs_height=height; } - sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } if( 0==parentWindowHandle && ( x != newX || y != newY ) ) { if(DEBUG_IMPLEMENTATION) { @@ -181,7 +168,7 @@ public class X11Window extends Window { nfs_x=x; nfs_y=y; } - sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } } @@ -190,9 +177,9 @@ public class X11Window extends Window { */ private void focusChanged(boolean focusGained) { if (focusGained) { - sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); } else { - sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + enqueueWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); } } @@ -208,5 +195,4 @@ public class X11Window extends Window { } private long windowHandleClose; - private long displayHandleClose; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index dec41b427..7a223026e 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -161,29 +161,13 @@ public class GLWindow extends Window implements GLAutoDrawable { shouldNotCallThis(); } - protected void dispose() { - if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.dispose() "+Thread.currentThread()+", start: "+this); - e1.printStackTrace(); - } - - if ( null != context && context.isCreated() && null != drawable && drawable.isRealized() ) { - helper.invokeGL(drawable, context, disposeAction, null); - } - - if (context != null) { - context.destroy(); - context = null; - } - if (drawable != null) { - drawable.setRealized(false); - drawable = null; - } - - if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.dispose() "+Thread.currentThread()+", fin: "+this); + class DisposeAction implements Runnable { + public void run() { + // Lock: Covered by DestroyAction .. + helper.dispose(GLWindow.this); } } + private DisposeAction disposeAction = new DisposeAction(); class DestroyAction implements Runnable { boolean deep; @@ -191,12 +175,35 @@ public class GLWindow extends Window implements GLAutoDrawable { this.deep = deep; } public void run() { + // Lock: Have to cover whole workflow (dispose all, context, drawable and window) windowLock(); try { if(null==window || window.isDestroyed()) { return; // nop } - dispose(); + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + Exception e1 = new Exception("GLWindow.destroy("+deep+") "+Thread.currentThread()+", start: "+GLWindow.this); + 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 (context != null && null != drawable && drawable.isRealized() ) { + context.destroy(); + context = null; + } + if (drawable != null) { + drawable.setRealized(false); + drawable = null; + } if(null!=window) { window.destroy(deep); @@ -205,6 +212,9 @@ public class GLWindow extends Window implements GLAutoDrawable { if(deep) { helper=null; } + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + System.out.println("GLWindow.destroy("+deep+") "+Thread.currentThread()+", fin: "+GLWindow.this); + } } finally { windowUnlock(); } @@ -243,6 +253,7 @@ public class GLWindow extends Window implements GLAutoDrawable { this.visible = visible; } public void run() { + // Lock: Have to cover whole workflow (window, may do nativeCreation, drawable and context) windowLock(); try{ window.setVisible(visible); @@ -489,7 +500,12 @@ public class GLWindow extends Window implements GLAutoDrawable { if(forceReshape) { sendReshape = true; } - helper.invokeGL(drawable, context, displayAction, initAction); + windowLock(); + try{ + helper.invokeGL(drawable, context, displayAction, initAction); + } finally { + windowUnlock(); + } } } } @@ -506,6 +522,7 @@ public class GLWindow extends Window implements GLAutoDrawable { public void swapBuffers() { if(drawable!=null && context != null) { + // Lock: Locked Surface/Window by MakeCurrent/Release if (context != GLContext.getCurrent()) { // Assume we should try to make the context current before swapping the buffers helper.invokeGL(drawable, context, swapBuffersAction, initAction); @@ -517,6 +534,7 @@ public class GLWindow extends Window implements GLAutoDrawable { class InitAction implements Runnable { public void run() { + // Lock: Locked Surface/Window by MakeCurrent/Release helper.init(GLWindow.this); startTime = System.currentTimeMillis(); curTime = startTime; @@ -528,15 +546,9 @@ public class GLWindow extends Window implements GLAutoDrawable { } private InitAction initAction = new InitAction(); - class DisposeAction implements Runnable { - public void run() { - helper.dispose(GLWindow.this); - } - } - private DisposeAction disposeAction = new DisposeAction(); - class DisplayAction implements Runnable { public void run() { + // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release if (sendReshape) { int width = getWidth(); int height = getHeight(); @@ -635,6 +647,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return null!=drawable ? drawable.getNativeWindow() : null; } + public long getHandle() { + return null!=drawable ? drawable.getHandle() : 0; + } + //---------------------------------------------------------------------- // GLDrawable methods that are not really needed // |