aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt')
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/Display.java116
-rw-r--r--src/newt/classes/com/sun/javafx/newt/DisplayActionThread.java118
-rw-r--r--src/newt/classes/com/sun/javafx/newt/Event.java9
-rw-r--r--src/newt/classes/com/sun/javafx/newt/KeyEvent.java2
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/NewtFactory.java14
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/Screen.java2
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/Window.java147
-rw-r--r--src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java171
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/opengl/broadcom/egl/Window.java2
-rw-r--r--src/newt/classes/com/sun/javafx/newt/util/EventDispatchThread.java209
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java43
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/x11/X11Display.java12
-rwxr-xr-xsrc/newt/classes/com/sun/javafx/newt/x11/X11Window.java19
-rwxr-xr-xsrc/newt/native/WindowsWindow.c2
-rwxr-xr-xsrc/newt/native/X11Window.c171
15 files changed, 672 insertions, 365 deletions
diff --git a/src/newt/classes/com/sun/javafx/newt/Display.java b/src/newt/classes/com/sun/javafx/newt/Display.java
index 0be8aedbc..ad4664ac8 100755
--- a/src/newt/classes/com/sun/javafx/newt/Display.java
+++ b/src/newt/classes/com/sun/javafx/newt/Display.java
@@ -35,9 +35,10 @@ package com.sun.javafx.newt;
import javax.media.nativewindow.*;
import com.sun.javafx.newt.impl.Debug;
+import com.sun.javafx.newt.util.EventDispatchThread;
import java.util.*;
-public abstract class Display implements Runnable {
+public abstract class Display {
public static final boolean DEBUG = Debug.debug("Display");
private static Class getDisplayClass(String type)
@@ -62,6 +63,7 @@ public abstract class Display implements Runnable {
return displayClass;
}
+ // Unique Display for each thread
private static ThreadLocal currentDisplayMap = new ThreadLocal();
/** Returns the thread local display map */
@@ -109,11 +111,11 @@ public abstract class Display implements Runnable {
return display;
}
- private static void dumpDisplayMap(String prefix) {
+ public static void dumpDisplayMap(String prefix) {
Map displayMap = getCurrentDisplayMap();
Set entrySet = displayMap.entrySet();
Iterator i = entrySet.iterator();
- System.err.println(prefix+" DisplayMap["+entrySet.size()+"] "+Thread.currentThread().getName());
+ System.err.println(prefix+" DisplayMap["+entrySet.size()+"] "+Thread.currentThread());
for(int j=0; i.hasNext(); j++) {
Map.Entry entry = (Map.Entry) i.next();
System.err.println(" ["+j+"] "+entry.getKey()+" -> "+entry.getValue());
@@ -128,58 +130,100 @@ public abstract class Display implements Runnable {
/** Make sure to reuse a Display with the same name */
protected static Display create(String type, String name) {
try {
+ if(DEBUG) {
+ dumpDisplayMap("Display.create("+name+") BEGIN");
+ }
Display display = getCurrentDisplay(name);
if(null==display) {
Class displayClass = getDisplayClass(type);
display = (Display) displayClass.newInstance();
display.name=name;
display.refCount=1;
- display.createNative();
+
+ if(NewtFactory.useEDT()) {
+ Thread current = Thread.currentThread();
+ display.eventDispatchThread = new EventDispatchThread(display, current.getThreadGroup(), current.getName());
+ display.eventDispatchThread.start();
+ final Display f_dpy = display;
+ display.eventDispatchThread.invokeAndWait(new Runnable() {
+ public void run() {
+ f_dpy.createNative();
+ }
+ } );
+ } else {
+ display.createNative();
+ }
if(null==display.aDevice) {
throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice");
}
setCurrentDisplay(display);
if(DEBUG) {
- System.err.println("Display.create("+name+") NEW: "+display+" "+Thread.currentThread().getName());
+ System.err.println("Display.create("+name+") NEW: "+display+" "+Thread.currentThread());
}
} else {
synchronized(display) {
display.refCount++;
if(DEBUG) {
- System.err.println("Display.create("+name+") REUSE: refCount "+display.refCount+", "+display+" "+Thread.currentThread().getName());
+ System.err.println("Display.create("+name+") REUSE: refCount "+display.refCount+", "+display+" "+Thread.currentThread());
}
}
}
+ if(DEBUG) {
+ dumpDisplayMap("Display.create("+name+") END");
+ }
+ return display;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static Display wrapHandle(String type, String name, AbstractGraphicsDevice aDevice) {
+ try {
+ Class displayClass = getDisplayClass(type);
+ Display display = (Display) displayClass.newInstance();
+ display.name=name;
+ display.aDevice=aDevice;
return display;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+ public EventDispatchThread getEDT() { return eventDispatchThread; }
+
public synchronized void destroy() {
+ if(DEBUG) {
+ dumpDisplayMap("Display.destroy("+name+") BEGIN");
+ }
refCount--;
if(0==refCount) {
removeCurrentDisplay(name);
if(DEBUG) {
- System.err.println("Display.destroy("+name+") REMOVE: "+this+" "+Thread.currentThread().getName());
+ System.err.println("Display.destroy("+name+") REMOVE: "+this+" "+Thread.currentThread());
+ }
+ if(null!=eventDispatchThread) {
+ final Display f_dpy = this;
+ eventDispatchThread.invokeAndWait(new Runnable() {
+ public void run() {
+ f_dpy.closeNative();
+ }
+ } );
+ } else {
+ closeNative();
+ }
+ aDevice = null;
+ if(null!=eventDispatchThread) {
+ eventDispatchThread.stop();
+ eventDispatchThread.waitUntilStopped();
+ eventDispatchThread=null;
}
- closeNative();
} else {
if(DEBUG) {
- System.err.println("Display.destroy("+name+") KEEP: refCount "+refCount+", "+this+" "+Thread.currentThread().getName());
+ System.err.println("Display.destroy("+name+") KEEP: refCount "+refCount+", "+this+" "+Thread.currentThread());
}
}
- }
-
- protected static Display wrapHandle(String type, String name, AbstractGraphicsDevice aDevice) {
- try {
- Class displayClass = getDisplayClass(type);
- Display display = (Display) displayClass.newInstance();
- display.name=name;
- display.aDevice=aDevice;
- return display;
- } catch (Exception e) {
- throw new RuntimeException(e);
+ if(DEBUG) {
+ dumpDisplayMap("Display.destroy("+name+") END");
}
}
@@ -191,32 +235,23 @@ public abstract class Display implements Runnable {
}
public long getHandle() {
- return aDevice.getHandle();
+ if(null!=aDevice) {
+ return aDevice.getHandle();
+ }
+ return 0;
}
public AbstractGraphicsDevice getGraphicsDevice() {
return aDevice;
}
- public synchronized void pumpMessages() {
- dispatchMessages();
- }
-
- /** calls {@link #pumpMessages} */
- public void run() {
- pumpMessages();
- }
-
- public static interface Action {
- public void run(Display display);
- }
-
- /** Calls {@link Display.Action#run(Display)} on all Display's
- bound to the current thread. */
- public static void runCurrentThreadDisplaysAction(Display.Action action) {
- Iterator iter = getCurrentDisplays().iterator(); // Thread local .. no sync necessary
- while(iter.hasNext()) {
- action.run((Display) iter.next());
+ public void pumpMessages() {
+ if(null!=eventDispatchThread) {
+ dispatchMessages();
+ } else {
+ synchronized(this) {
+ dispatchMessages();
+ }
}
}
@@ -226,6 +261,7 @@ public abstract class Display implements Runnable {
protected abstract void dispatchMessages();
+ protected EventDispatchThread eventDispatchThread = null;
protected String name;
protected int refCount;
protected AbstractGraphicsDevice aDevice;
diff --git a/src/newt/classes/com/sun/javafx/newt/DisplayActionThread.java b/src/newt/classes/com/sun/javafx/newt/DisplayActionThread.java
deleted file mode 100644
index 8f02148a2..000000000
--- a/src/newt/classes/com/sun/javafx/newt/DisplayActionThread.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2008 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.sun.javafx.newt;
-
-import javax.media.nativewindow.*;
-import com.sun.javafx.newt.impl.Debug;
-import java.util.*;
-
-public class DisplayActionThread extends Thread {
- private Object taskWorkerLock=new Object();
- private boolean isRunning = false;
- private boolean shouldStop = false;
- private List/*DisplayAction*/ displayActions = new ArrayList();
-
- public synchronized void addAction(Display.Action da) {
- List newListeners = (List) ((ArrayList) displayActions).clone();
- newListeners.add(da);
- displayActions = newListeners;
- }
-
- public synchronized void removeAction(Display.Action da) {
- List newListeners = (List) ((ArrayList) displayActions).clone();
- newListeners.remove(da);
- displayActions = newListeners;
- }
-
- public boolean isRunning() {
- synchronized(taskWorkerLock) {
- return isRunning;
- }
- }
-
- public void exit() {
- synchronized(taskWorkerLock) {
- if(isRunning) {
- shouldStop = true;
- taskWorkerLock.notifyAll();
- }
- }
- Map displayMap = Display.getCurrentDisplayMap();
- synchronized(displayMap) {
- displayMap.notifyAll();
- }
- }
-
- public void start() {
- synchronized(taskWorkerLock) {
- if(!isRunning) {
- shouldStop = false;
- taskWorkerLock.notifyAll();
- super.start();
- }
- }
- }
-
- public void run() {
- synchronized(taskWorkerLock) {
- isRunning = true;
- taskWorkerLock.notifyAll();
- }
- while(!shouldStop) {
- Map displayMap = Display.getCurrentDisplayMap();
- // wait for something todo ..
- synchronized(displayMap) {
- while(!shouldStop && displayMap.size()==0) {
- try {
- displayMap.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- Iterator iter = Display.getCurrentDisplays().iterator();
- while(iter.hasNext()) {
- Display display = (Display) iter.next();
- Iterator iterDA = displayActions.iterator();
- while(iterDA.hasNext()) {
- ((Display.Action)iterDA.next()).run(display);
- }
- }
- }
- synchronized(taskWorkerLock) {
- isRunning = false;
- taskWorkerLock.notifyAll();
- }
- }
-}
diff --git a/src/newt/classes/com/sun/javafx/newt/Event.java b/src/newt/classes/com/sun/javafx/newt/Event.java
index 7d2b24ba5..3c045c52b 100644
--- a/src/newt/classes/com/sun/javafx/newt/Event.java
+++ b/src/newt/classes/com/sun/javafx/newt/Event.java
@@ -74,4 +74,13 @@ public class Event {
public String toString() {
return "Event[sys:"+isSystemEvent()+", source:"+getSource()+", when:"+getWhen()+"]";
}
+
+ public static String toHexString(int hex) {
+ return "0x" + Integer.toHexString(hex);
+ }
+
+ public static String toHexString(long hex) {
+ return "0x" + Long.toHexString(hex);
+ }
+
}
diff --git a/src/newt/classes/com/sun/javafx/newt/KeyEvent.java b/src/newt/classes/com/sun/javafx/newt/KeyEvent.java
index 7e224dbad..c7450da67 100644
--- a/src/newt/classes/com/sun/javafx/newt/KeyEvent.java
+++ b/src/newt/classes/com/sun/javafx/newt/KeyEvent.java
@@ -53,7 +53,7 @@ public class KeyEvent extends InputEvent
public String toString() {
return "KeyEvent["+getEventTypeString(getEventType())+
- ", code "+keyCode+"(0x"+Integer.toHexString(keyCode)+"), char <"+keyChar+"> (0x"+Integer.toHexString((int)keyChar)+"), isActionKey "+isActionKey()+", "+super.toString()+"]";
+ ", code "+keyCode+"("+toHexString(keyCode)+"), char <"+keyChar+"> ("+toHexString((int)keyChar)+"), isActionKey "+isActionKey()+", "+super.toString()+"]";
}
public static String getEventTypeString(int type) {
diff --git a/src/newt/classes/com/sun/javafx/newt/NewtFactory.java b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java
index c4180eb46..6e25b19eb 100755
--- a/src/newt/classes/com/sun/javafx/newt/NewtFactory.java
+++ b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java
@@ -57,6 +57,20 @@ public abstract class NewtFactory {
return clazz;
}
+ private static boolean useEDT = true;
+
+ /**
+ * Toggles the usage of an EventDispatchThread while creating a Display.<br>
+ * The default is enabled.<br>
+ * The EventDispatchThread is thread local to the Display instance.<br>
+ */
+ public static synchronized void setUseEDT(boolean onoff) {
+ useEDT = onoff;
+ }
+
+ /** @see #setUseEDT(boolean) */
+ public static boolean useEDT() { return useEDT; }
+
/**
* Create a Display entity, incl native creation
*/
diff --git a/src/newt/classes/com/sun/javafx/newt/Screen.java b/src/newt/classes/com/sun/javafx/newt/Screen.java
index e347a69c2..9edd0b719 100755
--- a/src/newt/classes/com/sun/javafx/newt/Screen.java
+++ b/src/newt/classes/com/sun/javafx/newt/Screen.java
@@ -84,6 +84,8 @@ public abstract class Screen {
public synchronized void destroy() {
closeNative();
+ display = null;
+ aScreen = null;
}
protected static Screen wrapHandle(String type, Display display, AbstractGraphicsScreen aScreen) {
diff --git a/src/newt/classes/com/sun/javafx/newt/Window.java b/src/newt/classes/com/sun/javafx/newt/Window.java
index 85b8723f9..7bebe2125 100755
--- a/src/newt/classes/com/sun/javafx/newt/Window.java
+++ b/src/newt/classes/com/sun/javafx/newt/Window.java
@@ -34,6 +34,7 @@
package com.sun.javafx.newt;
import com.sun.javafx.newt.impl.Debug;
+import com.sun.javafx.newt.util.EventDispatchThread;
import javax.media.nativewindow.*;
import com.sun.nativewindow.impl.NWReflection;
@@ -85,7 +86,7 @@ public abstract class Window implements NativeWindow
return windowClass;
}
- protected static Window create(String type, long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) {
+ protected static Window create(String type, final long parentWindowHandle, Screen screen, final Capabilities caps, boolean undecorated) {
try {
Class windowClass;
if(caps.isOnscreen()) {
@@ -97,7 +98,17 @@ public abstract class Window implements NativeWindow
window.invalidate();
window.screen = screen;
window.setUndecorated(undecorated||0!=parentWindowHandle);
- window.createNative(parentWindowHandle, caps);
+ EventDispatchThread edt = screen.getDisplay().getEDT();
+ if(null!=edt) {
+ final Window f_win = window;
+ edt.invokeAndWait(new Runnable() {
+ public void run() {
+ f_win.createNative(parentWindowHandle, caps);
+ }
+ } );
+ } else {
+ window.createNative(parentWindowHandle, caps);
+ }
return window;
} catch (Throwable t) {
t.printStackTrace();
@@ -105,7 +116,7 @@ public abstract class Window implements NativeWindow
}
}
- protected static Window create(String type, Object[] cstrArguments, Screen screen, Capabilities caps, boolean undecorated) {
+ protected static Window create(String type, Object[] cstrArguments, Screen screen, final Capabilities caps, boolean undecorated) {
try {
Class windowClass = getWindowClass(type);
Class[] cstrArgumentTypes = getCustomConstructorArgumentTypes(windowClass);
@@ -120,7 +131,17 @@ public abstract class Window implements NativeWindow
window.invalidate();
window.screen = screen;
window.setUndecorated(undecorated);
- window.createNative(0, caps);
+ EventDispatchThread edt = screen.getDisplay().getEDT();
+ if(null!=edt) {
+ final Window f_win = window;
+ edt.invokeAndWait(new Runnable() {
+ public void run() {
+ f_win.createNative(0, caps);
+ }
+ } );
+ } else {
+ window.createNative(0, caps);
+ }
return window;
} catch (Throwable t) {
t.printStackTrace();
@@ -152,6 +173,25 @@ 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 AbstractGraphicsConfiguration config;
+ protected long windowHandle;
+ protected boolean fullscreen, visible;
+ protected int width, height, x, y;
+ protected int eventMask;
+
+ protected String title = "Newt Window";
+ protected boolean undecorated = false;
+
/**
* Create native windowHandle, ie creates a new native invisible window.
*
@@ -173,8 +213,8 @@ public abstract class Window implements NativeWindow
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName()+"[config "+config+
- ", windowHandle 0x"+Long.toHexString(getWindowHandle())+
- ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
+ ", windowHandle "+toHexString(getWindowHandle())+
+ ", surfaceHandle "+toHexString(getSurfaceHandle())+
", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
", visible "+isVisible()+
", undecorated "+undecorated+
@@ -202,18 +242,6 @@ public abstract class Window implements NativeWindow
return sb.toString();
}
- protected Screen screen;
-
- protected AbstractGraphicsConfiguration config;
- protected long windowHandle;
- protected Exception lockedStack = null;
- protected boolean fullscreen, visible;
- protected int width, height, x, y;
- protected int eventMask;
-
- protected String title = "Newt Window";
- protected boolean undecorated = false;
-
public String getTitle() {
return title;
}
@@ -236,31 +264,55 @@ public abstract class Window implements NativeWindow
//
// NativeWindow impl
//
+ private Thread owner;
+ private int recursionCount;
+ protected Exception lockedStack = null;
- public synchronized int lockSurface() throws NativeWindowException {
+ /** Recursive and blocking lockSurface() implementation */
+ public synchronized int lockSurface() {
// We leave the ToolkitLock lock to the specializtion's discretion,
// ie the implicit JAWTWindow in case of AWTWindow
- if (null!=lockedStack) {
- lockedStack.printStackTrace();
- throw new NativeWindowException("NEWT Surface already locked - "+Thread.currentThread().getName()+" "+this);
+ Thread cur = Thread.currentThread();
+ if (owner == cur) {
+ ++recursionCount;
+ return LOCK_SUCCESS;
}
-
- lockedStack = new Exception("NEWT Surface previously locked by "+Thread.currentThread().getName());
+ while (owner != null) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ owner = cur;
+ lockedStack = new Exception("NEWT Surface previously locked by "+Thread.currentThread());
return LOCK_SUCCESS;
}
- public synchronized void unlockSurface() {
- if (null!=lockedStack) {
- lockedStack = null;
- } else {
- throw new NativeWindowException("NEWT Surface not locked");
+ /** Recursive and unblocking unlockSurface() implementation */
+ public synchronized void unlockSurface() throws NativeWindowException {
+ Thread cur = Thread.currentThread();
+ if (owner != cur) {
+ lockedStack.printStackTrace();
+ throw new NativeWindowException(cur+": Not owner, owner is "+owner);
}
+ if (recursionCount > 0) {
+ --recursionCount;
+ return;
+ }
+ owner = null;
+ lockedStack = null;
+ notifyAll();
// We leave the ToolkitLock unlock to the specializtion's discretion,
// ie the implicit JAWTWindow in case of AWTWindow
}
public synchronized boolean isSurfaceLocked() {
- return null!=lockedStack;
+ return null!=owner;
+ }
+
+ public synchronized Thread getSurfaceLockOwner() {
+ return owner;
}
public synchronized Exception getLockedStack() {
@@ -268,8 +320,13 @@ public abstract class Window implements NativeWindow
}
public synchronized void destroy() {
+ destroy(false);
+ }
+
+ /** @param deep If true, the linked Screen and Display will be destroyed as well. */
+ public synchronized void destroy(boolean deep) {
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.destroy() start "+Thread.currentThread().getName());
+ System.out.println("Window.destroy() start (deep "+deep+" - "+Thread.currentThread());
}
synchronized(surfaceUpdatedListeners) {
surfaceUpdatedListeners = new ArrayList();
@@ -283,16 +340,32 @@ public abstract class Window implements NativeWindow
synchronized(keyListeners) {
keyListeners = new ArrayList();
}
- closeNative();
+ Screen scr = screen;
+ Display dpy = screen.getDisplay();
+ EventDispatchThread edt = dpy.getEDT();
+ if(null!=edt) {
+ final Window f_win = this;
+ edt.invokeAndWait(new Runnable() {
+ public void run() {
+ f_win.closeNative();
+ }
+ } );
+ } else {
+ closeNative();
+ }
invalidate();
+ if(deep) {
+ scr.destroy();
+ dpy.destroy();
+ }
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.destroy() end "+Thread.currentThread().getName());
+ System.out.println("Window.destroy() end "+Thread.currentThread());
}
}
public void invalidate() {
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
- Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread().getName());
+ Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread());
e.printStackTrace();
}
screen = null;
@@ -415,7 +488,7 @@ public abstract class Window implements NativeWindow
protected void windowDestroyNotify() {
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyeNotify start "+Thread.currentThread().getName());
+ System.out.println("Window.windowDestroyeNotify start "+Thread.currentThread());
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
@@ -425,13 +498,13 @@ public abstract class Window implements NativeWindow
}
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread().getName());
+ System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread());
}
}
protected void windowDestroyed() {
if(DEBUG_WINDOW_EVENT) {
- System.out.println("Window.windowDestroyed "+Thread.currentThread().getName());
+ System.out.println("Window.windowDestroyed "+Thread.currentThread());
}
invalidate();
}
diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java
index 52f368148..aebf8f9dd 100644
--- a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java
@@ -41,45 +41,22 @@ import java.util.*;
/**
* An implementation of {@link Window} which is customized for OpenGL
- * use, and which implements the {@link
- * javax.media.opengl.GLAutoDrawable} interface. For convenience, this
- * window class guarantees that its OpenGL context is current inside
- * the various EventListeners' callbacks (MouseListener, KeyListener,
- * etc.).<P>
- *
- * Best performance is currently achieved with default settings,
- * {@link #setEventHandlerMode} to {@link #EVENT_HANDLER_GL_NONE}
- * and one thread per GLWindow. To ensure compatibility with the
- * underlying platform, window shall also be created within your
- * working thread. See comment at {@link #setRunPumpMessages}.
+ * use, and which implements the {@link javax.media.opengl.GLAutoDrawable} interface.
+ * <P>
+ * This implementation does not make the OpenGL context current<br>
+ * before calling the various input EventListener callbacks (MouseListener, KeyListener,
+ * etc.).<br>
+ * This design decision is made to favor a more performant and simplified
+ * implementation, as well as the event dispatcher shall be allowed
+ * not having a notion about OpenGL.
+ * <p>
*/
public class GLWindow extends Window implements GLAutoDrawable {
- /**
- * Event handling mode: EVENT_HANDLER_GL_NONE.
- * No GL context is current, while calling the EventListener.
- * This might be inconvenient, but don't impact the performance.
- * Also
- *
- * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int)
- */
- public static final int EVENT_HANDLER_GL_NONE = 0;
-
- /**
- * Event handling mode: EVENT_HANDLER_GL_CURRENT.
- * The GL context is made current, while calling the EventListener.
- * This might be convenient, but impacts the performance
- * due to context switches.
- *
- * This is the default setting!
- *
- * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int)
- */
- public static final int EVENT_HANDLER_GL_CURRENT = (1 << 0);
-
private static List/*GLWindow*/ glwindows = new ArrayList();
+ private boolean ownerOfDisplayAndScreen;
private Window window;
- private boolean runPumpMessages = true;
+ private boolean runPumpMessages;
/** Constructor. Do not call this directly -- use {@link
create()} instead. */
@@ -87,6 +64,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
this.ownerOfDisplayAndScreen = ownerOfDisplayAndScreen;
this.window = window;
this.window.setAutoDrawableClient(true);
+ this.runPumpMessages = ( null == getScreen().getDisplay().getEDT() ) ;
window.addWindowListener(new WindowListener() {
public void windowResized(WindowEvent e) {
sendReshape = true;
@@ -166,9 +144,16 @@ public class GLWindow extends Window implements GLAutoDrawable {
*
* Best performance has been achieved with one GLWindow per thread.<br>
*
+ * Enabling local pump messages while using the EDT,
+ * {@link com.sun.javafx.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().getEDT() ) {
+ throw new GLException("GLWindow.setRunPumpMessages(true) - Can't do with EDT on");
+ }
runPumpMessages = onoff;
}
@@ -182,7 +167,7 @@ public class GLWindow extends Window implements GLAutoDrawable {
protected void dispose(boolean regenerate) {
if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
- Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", 1: "+this);
+ Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", 1: "+this);
e1.printStackTrace();
}
@@ -213,21 +198,22 @@ public class GLWindow extends Window implements GLAutoDrawable {
}
drawable = factory.createGLDrawable(nw);
drawable.setRealized(true);
- if(getSurfaceHandle()==0) {
- throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this);
- }
context = drawable.createContext(null);
sendReshape = true; // ensure a reshape event is send ..
}
if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
- System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", fin: "+this);
+ System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", fin: "+this);
}
}
public synchronized void destroy() {
+ destroy(false);
+ }
+
+ public synchronized void destroy(boolean deep) {
if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
- Exception e1 = new Exception("GLWindow.destroy "+Thread.currentThread().getName()+", 1: "+this);
+ Exception e1 = new Exception("GLWindow.destroy "+Thread.currentThread()+", 1: "+this);
e1.printStackTrace();
}
@@ -240,17 +226,17 @@ public class GLWindow extends Window implements GLAutoDrawable {
Screen _screen = null;
Display _device = null;
if(null!=window) {
- if(ownerOfDisplayAndScreen) {
+ if(!deep && ownerOfDisplayAndScreen) {
_screen = getScreen();
if(null != _screen) {
_device = _screen.getDisplay();
}
}
- window.destroy();
+ window.destroy(deep);
}
if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
- System.out.println("GLWindow.destroy "+Thread.currentThread().getName()+", fin: "+this);
+ System.out.println("GLWindow.destroy "+Thread.currentThread()+", fin: "+this);
}
drawable = null;
@@ -271,21 +257,11 @@ public class GLWindow extends Window implements GLAutoDrawable {
perfLog = v;
}
- /**
- * Sets the event handling mode.
- *
- * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_NONE
- * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_CURRENT
- */
- public void setEventHandlerMode(int mode) {
- eventHandlerMode = mode;
- }
-
- public int getEventHandlerMode() {
- return eventHandlerMode;
- }
-
public void setVisible(boolean visible) {
+ if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
+ System.out.println(Thread.currentThread()+" GLWindow.setVisible("+visible+") START ; isVisible "+this.visible+" ; has context "+(null!=context));
+ }
+ this.visible=visible;
window.setVisible(visible);
if (visible && context == null) {
NativeWindow nw;
@@ -298,12 +274,12 @@ public class GLWindow extends Window implements GLAutoDrawable {
factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
drawable = factory.createGLDrawable(nw);
drawable.setRealized(true);
- if(getSurfaceHandle()==0) {
- throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this);
- }
context = drawable.createContext(null);
sendReshape = true; // ensure a reshape event is send ..
}
+ if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
+ System.out.println(Thread.currentThread()+" GLWindow.setVisible("+visible+") END ; has context "+(null!=context));
+ }
}
public Screen getScreen() {
@@ -423,8 +399,6 @@ public class GLWindow extends Window implements GLAutoDrawable {
// OpenGL-related methods and state
//
- private static int eventHandlerMode = EVENT_HANDLER_GL_CURRENT;
- private static boolean autoSwapBufferMode = true;
private GLDrawableFactory factory;
private GLDrawable drawable;
private GLContext context;
@@ -469,72 +443,14 @@ public class GLWindow extends Window implements GLAutoDrawable {
helper.removeGLEventListener(listener);
}
- class DisplayPumpMessage implements Display.Action {
- public void run(Display display) {
- if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) {
- display.run();
- } else {
- helper.setAutoSwapBufferMode(false);
- try {
- helper.invokeGL(drawable, context, display, initAction);
- } finally {
- helper.setAutoSwapBufferMode(autoSwapBufferMode);
- }
- }
- }
- }
- private DisplayPumpMessage displayPumpMessage = new DisplayPumpMessage();
-
- static class DisplayPumpMessageStatic implements Display.Action {
- public void run(Display display) {
- display.run();
- }
- }
- private static DisplayPumpMessageStatic displayPumpMessageStatic = new DisplayPumpMessageStatic();
-
- /**
- * @see #setRunPumpMessages
- * @deprecated EXPERIMENTAL, semantic is about to be removed after further verification.
- */
- public static void runCurrentThreadPumpMessage() {
- Exception safedE = null;
-
- if( 0 != (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) {
- // for all: setup / init / makeCurrent
- for(Iterator i = glwindows.iterator(); i.hasNext(); ) {
- GLWindow glw = (GLWindow) i.next();
- glw.helper.setAutoSwapBufferMode(false);
- glw.helper.invokeGL(glw.drawable, glw.context, null, glw.initAction);
- }
- }
-
- try {
- Display.runCurrentThreadDisplaysAction(displayPumpMessageStatic);
- } catch (Exception e) {
- safedE=e;
- }
-
- if( 0 != (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) {
- // for all: reset
- for(Iterator i = glwindows.iterator(); i.hasNext(); ) {
- GLWindow glw = (GLWindow) i.next();
- glw.helper.setAutoSwapBufferMode(autoSwapBufferMode);
- }
- }
-
- if(null!=safedE) {
- throw new GLException(safedE);
- }
- }
-
public void display() {
display(false);
}
public void display(boolean forceReshape) {
- if(getSurfaceHandle()!=0) {
+ if(window!=null && drawable!=null && context != null) {
if(runPumpMessages) {
- displayPumpMessage.run(window.getScreen().getDisplay());
+ window.getScreen().getDisplay().pumpMessages();
}
if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) {
dispose(true);
@@ -552,24 +468,24 @@ public class GLWindow extends Window implements GLAutoDrawable {
}
private void sendDisposeEvent() {
- if(disposeAction!=null && drawable!=null && context != null && window!=null && getSurfaceHandle()!=0) {
+ if(drawable!=null && context != null) {
helper.invokeGL(drawable, context, disposeAction, null);
}
}
/** This implementation uses a static value */
public void setAutoSwapBufferMode(boolean onOrOff) {
- autoSwapBufferMode = onOrOff;
+ helper.setAutoSwapBufferMode(onOrOff);
}
/** This implementation uses a static value */
public boolean getAutoSwapBufferMode() {
- return autoSwapBufferMode;
+ return helper.getAutoSwapBufferMode();
}
public void swapBuffers() {
- if(getSurfaceHandle()!=0) {
- if (context != null && context != GLContext.getCurrent()) {
+ if(drawable!=null && context != null) {
+ if (context != GLContext.getCurrent()) {
// Assume we should try to make the context current before swapping the buffers
helper.invokeGL(drawable, context, swapBuffersAction, initAction);
} else {
@@ -638,7 +554,6 @@ public class GLWindow extends Window implements GLAutoDrawable {
private long curTime = 0;
private long lastCheck = 0;
private int totalFrames = 0, lastFrames = 0;
- private boolean ownerOfDisplayAndScreen;
class SwapBuffersAction implements Runnable {
public void run() {
diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/broadcom/egl/Window.java b/src/newt/classes/com/sun/javafx/newt/opengl/broadcom/egl/Window.java
index 7d087416c..11672dde3 100755
--- a/src/newt/classes/com/sun/javafx/newt/opengl/broadcom/egl/Window.java
+++ b/src/newt/classes/com/sun/javafx/newt/opengl/broadcom/egl/Window.java
@@ -148,7 +148,7 @@ public class Window extends com.sun.javafx.newt.Window {
throw new NativeWindowException("Error creating EGLGraphicsConfiguration from id: "+cfgID+", "+this);
}
if(DEBUG_IMPLEMENTATION) {
- System.out.println("BCEGL Window.windowCreated(): 0x"+Integer.toHexString(cfgID)+", "+width+"x"+height+", "+config);
+ System.out.println("BCEGL Window.windowCreated(): "+toHexString(cfgID)+", "+width+"x"+height+", "+config);
}
}
diff --git a/src/newt/classes/com/sun/javafx/newt/util/EventDispatchThread.java b/src/newt/classes/com/sun/javafx/newt/util/EventDispatchThread.java
new file mode 100644
index 000000000..f8b205a8b
--- /dev/null
+++ b/src/newt/classes/com/sun/javafx/newt/util/EventDispatchThread.java
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ */
+
+package com.sun.javafx.newt.util;
+
+import com.sun.javafx.newt.Display;
+import java.util.*;
+
+public class EventDispatchThread {
+ private ThreadGroup threadGroup;
+ private volatile boolean shouldStop = false;
+ private TaskWorker taskWorker = null;
+ private Object taskWorkerLock = new Object();
+ private ArrayList tasks = new ArrayList(); // one shot tasks
+ private Display display = null;
+ private String name;
+ private long edtPollGranularity = 10;
+
+ public EventDispatchThread(Display display, ThreadGroup tg, String name) {
+ this.display = display;
+ this.threadGroup = tg;
+ this.name=new String("EDT-"+name);
+ }
+
+ public String getName() { return name; }
+
+ public ThreadGroup getThreadGroup() { return threadGroup; }
+
+ public void start() {
+ start(false);
+ }
+
+ /**
+ * @param externalStimuli true indicates that another thread stimulates,
+ * ie. calls this TaskManager's run() loop method.
+ * Hence no own thread is started in this case.
+ *
+ * @return The started Runnable, which handles the run-loop.
+ * Usefull in combination with externalStimuli=true,
+ * so an external stimuli can call it.
+ */
+ public Runnable start(boolean externalStimuli) {
+ synchronized(taskWorkerLock) {
+ if(null==taskWorker) {
+ taskWorker = new TaskWorker(threadGroup, name);
+ }
+ if(!taskWorker.isRunning()) {
+ shouldStop = false;
+ taskWorker.start(externalStimuli);
+ }
+ taskWorkerLock.notifyAll();
+ }
+ return taskWorker;
+ }
+
+ public void stop() {
+ synchronized(taskWorkerLock) {
+ if(null!=taskWorker && taskWorker.isRunning()) {
+ shouldStop = true;
+ }
+ taskWorkerLock.notifyAll();
+ }
+ }
+
+ public boolean isEDTThread(Thread thread) {
+ return taskWorker == thread;
+ }
+
+ public boolean isRunning() {
+ return null!=taskWorker && taskWorker.isRunning() ;
+ }
+
+ public void invokeLater(Runnable task) {
+ if(task == null) {
+ return;
+ }
+ synchronized(taskWorkerLock) {
+ tasks.add(task);
+ taskWorkerLock.notifyAll();
+ }
+ }
+
+ public void invokeAndWait(Runnable task) {
+ if(task == null) {
+ return;
+ }
+ invokeLater(task);
+ waitOnWorker();
+ }
+
+ public void waitOnWorker() {
+ synchronized(taskWorkerLock) {
+ if(null!=taskWorker && taskWorker.isRunning() && tasks.size()>0 && taskWorker != Thread.currentThread() ) {
+ try {
+ taskWorkerLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void waitUntilStopped() {
+ synchronized(taskWorkerLock) {
+ while(null!=taskWorker && taskWorker.isRunning() && taskWorker != Thread.currentThread() ) {
+ try {
+ taskWorkerLock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ class TaskWorker extends Thread {
+ boolean isRunning = false;
+ boolean externalStimuli = false;
+
+ public TaskWorker(ThreadGroup tg, String name) {
+ super(tg, name);
+ }
+
+ public synchronized boolean isRunning() {
+ return isRunning;
+ }
+
+ public void start(boolean externalStimuli) throws IllegalThreadStateException {
+ synchronized(this) {
+ this.externalStimuli = externalStimuli;
+ isRunning = true;
+ }
+ if(!externalStimuli) {
+ super.start();
+ }
+ }
+
+ public void run() {
+ while(!shouldStop) {
+ try {
+ // wait for something todo ..
+ synchronized(taskWorkerLock) {
+ while(!shouldStop && tasks.size()==0) {
+ try {
+ display.pumpMessages(); // event dispatch
+ taskWorkerLock.wait(edtPollGranularity);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ if(tasks.size()>0) {
+ Runnable task = (Runnable) tasks.remove(0);
+ task.run();
+ taskWorkerLock.notifyAll();
+ }
+ }
+ display.pumpMessages(); // event dispatch
+ } catch (Throwable t) {
+ // handle errors ..
+ t.printStackTrace();
+ } finally {
+ // epilog - unlock locked stuff
+ }
+ if(externalStimuli) break; // no loop if called by external stimuli
+ }
+ synchronized(this) {
+ isRunning = !shouldStop;
+ }
+ if(!isRunning) {
+ synchronized(taskWorkerLock) {
+ taskWorkerLock.notifyAll();
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java
index d044d61b5..5749039aa 100755
--- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java
+++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java
@@ -53,16 +53,40 @@ public class WindowsWindow extends Window {
public WindowsWindow() {
}
- public long getSurfaceHandle() {
- if (hdc == 0 && 0!=windowHandle) {
+ Thread hdcOwner = null;
+
+ public synchronized 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);
+ }
hdc = GetDC(windowHandle);
hmon = MonitorFromWindow(windowHandle);
- if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
- Exception e = new Exception("!!! Window new surface handle "+Thread.currentThread().getName()+
- ", HWND 0x"+Long.toHexString(windowHandle)+", HDC 0x"+Long.toHexString(hdc)+", HMON 0x"+Long.toHexString(hmon));
- e.printStackTrace();
+ 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);
}
+ ReleaseDC(windowHandle, hdc);
+ hdc=0;
+ hdcOwner=null;
}
+ super.unlockSurface();
+ }
+
+ public long getSurfaceHandle() {
return hdc;
}
@@ -72,7 +96,7 @@ public class WindowsWindow extends Window {
if (hmon != _hmon) {
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
Exception e = new Exception("!!! Window Device Changed "+Thread.currentThread().getName()+
- ", HMON 0x"+Long.toHexString(hmon)+" -> 0x"+Long.toHexString(_hmon));
+ ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon));
e.printStackTrace();
}
hmon = _hmon;
@@ -87,7 +111,7 @@ public class WindowsWindow extends Window {
ReleaseDC(windowHandle, hdc);
hdc=0;
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
- Exception e = new Exception("!!! Window surface handle disposed "+Thread.currentThread().getName());
+ Exception e = new Exception("!!! Window surface handle disposed "+Thread.currentThread().getName()+", "+Thread.currentThread());
e.printStackTrace();
}
}
@@ -110,7 +134,8 @@ public class WindowsWindow extends Window {
windowHandleClose = windowHandle;
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
Exception e = new Exception("!!! Window new window handle "+Thread.currentThread().getName()+
- ", HWND 0x"+Long.toHexString(windowHandle));
+ " (Parent HWND "+toHexString(parentWindowHandle)+
+ ") : HWND "+toHexString(windowHandle)+", "+Thread.currentThread());
e.printStackTrace();
}
}
diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java
index 5a2e0ad5d..297f98edb 100755
--- a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java
+++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java
@@ -87,11 +87,23 @@ public class X11Display extends Display {
protected long getJavaObjectAtom() { return javaObjectAtom; }
protected long getWindowDeleteAtom() { return windowDeleteAtom; }
+ protected void lockDisplay() {
+ LockDisplay(getHandle());
+ }
+
+ protected void unlockDisplay() {
+ UnlockDisplay(getHandle());
+ }
+
+
//----------------------------------------------------------------------
// Internals only
//
private static native boolean initIDs();
+ private native void LockDisplay(long handle);
+ private native void UnlockDisplay(long handle);
+
private native void CompleteDisplay(long handle);
private native void DispatchMessages(long display, long javaObjectAtom, long windowDeleteAtom);
diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java
index 46e797c21..94eb98299 100755
--- a/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java
+++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java
@@ -85,6 +85,25 @@ public class X11Window extends Window {
super.windowDestroyed();
}
+ public synchronized int lockSurface() throws NativeWindowException {
+ int res = super.lockSurface();
+ if(LOCK_SUCCESS == res) {
+ ((X11Display)(screen.getDisplay())).lockDisplay();
+ }
+ 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());
+ }
+ ((X11Display)(screen.getDisplay())).unlockDisplay();
+ super.unlockSurface();
+ }
+
public void setVisible(boolean visible) {
if(0!=windowHandle && this.visible!=visible) {
this.visible=visible;
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 9d3d76bde..5445ca372 100755
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -711,6 +711,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message,
return DefWindowProc(wnd, message, wParam, lParam);
}
+ // DBG_PRINT("*** WindowsWindow: window %p -> %p, 0x%X %d/%d\n", wnd, window, message, (int)LOWORD(lParam), (int)HIWORD(lParam));
+
switch (message) {
//
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 0242678d1..097d68cca 100755
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -166,11 +166,15 @@ static jmethodID sendKeyEventID = NULL;
static jmethodID displayCompletedID = NULL;
-static void _throwNewRuntimeException(JNIEnv *env, const char* msg, ...)
+static void _throwNewRuntimeException(Display * unlockDisplay, JNIEnv *env, const char* msg, ...)
{
char buffer[512];
va_list ap;
+ if(NULL!=unlockDisplay) {
+ XUnlockDisplay(unlockDisplay);
+ }
+
va_start(ap, msg);
vsnprintf(buffer, sizeof(buffer), msg, ap);
va_end(ap);
@@ -192,6 +196,10 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Display_initIDs
{
jclass c;
+ if( 0 == XInitThreads() ) {
+ fprintf(stderr, "Warning: XInitThreads() failed\n");
+ }
+
displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V");
if (displayCompletedID == NULL) {
return JNI_FALSE;
@@ -228,6 +236,37 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Display_initIDs
return JNI_TRUE;
}
+/*
+ * Class: com_sun_javafx_newt_x11_X11Display
+ * Method: LockDisplay
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_LockDisplay
+ (JNIEnv *env, jobject obj, jlong display)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "given display connection is NULL\n");
+ }
+ XLockDisplay(dpy) ;
+}
+
+
+/*
+ * Class: com_sun_javafx_newt_x11_X11Display
+ * Method: UnlockDisplay
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_UnlockDisplay
+ (JNIEnv *env, jobject obj, jlong display)
+{
+ Display * dpy = (Display *)(intptr_t)display;
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "given display connection is NULL\n");
+ }
+ XUnlockDisplay(dpy) ;
+}
+
/*
* Class: com_sun_javafx_newt_x11_X11Display
@@ -240,22 +279,27 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_CompleteDisplay
Display * dpy = (Display *)(intptr_t)display;
jlong javaObjectAtom;
jlong windowDeleteAtom;
+
if(dpy==NULL) {
- _throwNewRuntimeException(env, "given display connection is NULL\n");
+ _throwNewRuntimeException(NULL, env, "given display connection is NULL\n");
}
+ XLockDisplay(dpy) ;
javaObjectAtom = (jlong) XInternAtom(dpy, "JOGL_JAVA_OBJECT", False);
if(None==javaObjectAtom) {
- _throwNewRuntimeException(env, "could not create Atom JOGL_JAVA_OBJECT, bail out!\n");
+ _throwNewRuntimeException(dpy, env, "could not create Atom JOGL_JAVA_OBJECT, bail out!\n");
return;
}
windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False);
if(None==windowDeleteAtom) {
- _throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!\n");
+ _throwNewRuntimeException(dpy, env, "could not create Atom WM_DELETE_WINDOW, bail out!\n");
return;
}
+ // XSetCloseDownMode(dpy, RetainTemporary); // Just a try ..
+ XUnlockDisplay(dpy) ;
+
DBG_PRINT1("X11: X11Display_completeDisplay dpy %p\n", dpy);
(*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom);
@@ -285,7 +329,8 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon
{
jobject test = (jobject) getPtrOut32Long(jogl_java_object_data);
if( ! (jwindow==test) ) {
- _throwNewRuntimeException(env, "Internal Error .. Encoded Window ref not the same %p != %p !\n", jwindow, test);
+ _throwNewRuntimeException(dpy, env, "Internal Error .. Encoded Window ref not the same %p != %p !\n", jwindow, test);
+ return;
}
}
@@ -311,24 +356,25 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j
&nitems_return, &bytes_after_return, &jogl_java_object_data_pp);
if ( Success != res ) {
- _throwNewRuntimeException(env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, bail out!\n",
+ _throwNewRuntimeException(dpy, env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, bail out!\n",
res, nitems_return, bytes_after_return);
return NULL;
}
if(actual_type_return!=(Atom)javaObjectAtom || nitems_return<nitems_32 || NULL==jogl_java_object_data_pp) {
XFree(jogl_java_object_data_pp);
- _throwNewRuntimeException(env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, bail out!\n",
+ _throwNewRuntimeException(dpy, env, "could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, bail out!\n",
res, nitems_return, bytes_after_return, (long)actual_type_return, javaObjectAtom);
return NULL;
}
}
+
jwindow = (jobject) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ;
XFree(jogl_java_object_data_pp);
#ifdef VERBOSE_ON
if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) {
- _throwNewRuntimeException(env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !\n", jwindow);
+ _throwNewRuntimeException(NULL, env, "fetched Atom JOGL_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !\n", jwindow);
}
#endif
return jwindow;
@@ -343,10 +389,24 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DispatchMessages
(JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong wmDeleteAtom)
{
Display * dpy = (Display *) (intptr_t) display;
- int num_events = 0;
+ int num_events = 100;
+
+ if ( NULL == dpy ) {
+ return;
+ }
// Periodically take a break
- while( num_events<100 && XPending(dpy)>0 ) {
+ while( num_events > 0 ) {
+
+ XLockDisplay(dpy) ;
+
+ // num_events = XPending(dpy); // XEventsQueued(dpy, QueuedAfterFlush); // I/O Flush ..
+ // num_events = XEventsQueued(dpy, QueuedAlready); // Better, no I/O ..
+ if ( 0 >= XEventsQueued(dpy, QueuedAlready) ) {
+ XUnlockDisplay(dpy) ;
+ return;
+ }
+
jobject jwindow = NULL;
XEvent evt;
KeySym keySym;
@@ -354,23 +414,41 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DispatchMessages
char text[255];
XNextEvent(dpy, &evt);
- num_events++;
+ num_events--;
if( 0==evt.xany.window ) {
- _throwNewRuntimeException(env, "event window NULL, bail out!\n");
+ _throwNewRuntimeException(dpy, env, "event window NULL, bail out!\n");
+ return ;
}
if(dpy!=evt.xany.display) {
- _throwNewRuntimeException(env, "wrong display");
- continue;
+ _throwNewRuntimeException(dpy, env, "wrong display, bail out!\n");
+ return ;
}
jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom);
+
if(NULL==jwindow) {
// just leave .. _throwNewRuntimeException(env, "could not fetch Java Window object, bail out!\n");
+ XUnlockDisplay(dpy) ;
return;
}
switch(evt.type) {
+ case KeyRelease:
+ case KeyPress:
+ if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
+ keyChar=text[0];
+ } else {
+ keyChar=0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ XUnlockDisplay(dpy) ;
+
+ switch(evt.type) {
case ButtonPress:
(*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED,
(jint) evt.xbutton.state,
@@ -387,21 +465,11 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DispatchMessages
(jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/);
break;
case KeyPress:
- if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
- keyChar=text[0];
- } else {
- keyChar=0;
- }
(*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED,
(jint) evt.xkey.state,
X11KeySym2NewtVKey(keySym), (jchar) keyChar);
break;
case KeyRelease:
- if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) {
- keyChar=text[0];
- } else {
- keyChar=0;
- }
(*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED,
(jint) evt.xkey.state,
X11KeySym2NewtVKey(keySym), (jchar) keyChar);
@@ -456,7 +524,7 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DispatchMessages
default:
DBG_PRINT3("X11: event . unhandled %d 0x%X call 0x%X\n", evt.type, evt.type, evt.xunmap.window);
}
- }
+ }
}
@@ -474,10 +542,13 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Screen_GetScreen
{
Display * dpy = (Display *)(intptr_t)display;
Screen * scrn= NULL;
+
if(dpy==NULL) {
- fprintf(stderr, "[GetScreen] invalid display connection..\n");
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
return 0;
}
+ XLockDisplay(dpy);
+
scrn = ScreenOfDisplay(dpy,screen_index);
if(scrn==NULL) {
scrn=DefaultScreenOfDisplay(dpy);
@@ -485,6 +556,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Screen_GetScreen
if(scrn==NULL) {
fprintf(stderr, "couldn't get screen ..\n");
}
+ XUnlockDisplay(dpy) ;
return (jlong) (intptr_t) scrn;
}
@@ -564,15 +636,17 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow
DBG_PRINT4( "X11: CreateWindow %x/%d %dx%d\n", x, y, width, height);
if(dpy==NULL) {
- fprintf(stderr, "[CreateWindow] invalid display connection..\n");
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
return 0;
}
if(visualID<0) {
- fprintf(stderr, "[CreateWindow] invalid VisualID ..\n");
+ _throwNewRuntimeException(NULL, env, "invalid VisualID ..\n");
return 0;
}
+ XLockDisplay(dpy) ;
+
XSync(dpy, False);
scrn = ScreenOfDisplay(dpy, screen_index);
@@ -594,7 +668,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow
if (visual==NULL)
{
- _throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!\n");
+ _throwNewRuntimeException(dpy, env, "could not query Visual by given VisualID, bail out!\n");
return 0;
}
@@ -652,6 +726,8 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow
*/
}
+ XUnlockDisplay(dpy) ;
+
DBG_PRINT2( "X11: [CreateWindow] created window %p on display %p\n", window, dpy);
(*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) window);
@@ -670,13 +746,20 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_CloseWindow
Window w = (Window)window;
jobject jwindow;
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
+ return;
+ }
+ XLockDisplay(dpy) ;
+
jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom);
if(NULL==jwindow) {
- _throwNewRuntimeException(env, "could not fetch Java Window object, bail out!\n");
+ _throwNewRuntimeException(dpy, env, "could not fetch Java Window object, bail out!\n");
return;
}
if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
- _throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!\n");
+ _throwNewRuntimeException(dpy, env, "Internal Error .. Window global ref not the same!\n");
+ return;
}
(*env)->DeleteGlobalRef(env, jwindow);
@@ -690,6 +773,9 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_CloseWindow
XSync(dpy, False);
XDestroyWindow(dpy, w);
XSync(dpy, False);
+
+ XUnlockDisplay(dpy) ;
+
(*env)->CallVoidMethod(env, obj, windowDestroyedID);
}
@@ -704,6 +790,13 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setVisible0
Display * dpy = (Display *) (intptr_t) display;
Window w = (Window)window;
DBG_PRINT1( "X11: setVisible0 vis %d\n", visible);
+
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
+ return;
+ }
+ XLockDisplay(dpy) ;
+
XSync(dpy, False);
if(visible==JNI_TRUE) {
XMapRaised(dpy, w);
@@ -720,6 +813,7 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setVisible0
XUnmapWindow(dpy, w);
XSync(dpy, False);
}
+ XUnlockDisplay(dpy) ;
}
#define MWM_FULLSCREEN 1
@@ -746,6 +840,12 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setSize0
DBG_PRINT6( "X11: setSize0 %d/%d %dx%d, dec %d, vis %d\n", x, y, width, height, decorationToggle, setVisible);
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
+ return;
+ }
+ XLockDisplay(dpy) ;
+
XSync(dpy, False);
if(setVisible==JNI_TRUE) {
@@ -784,6 +884,7 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setSize0
XReparentWindow( dpy, w, parent, x, y );
XSync(dpy, False);
+ XUnlockDisplay(dpy) ;
}
/*
@@ -799,9 +900,17 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setPosition0
XWindowChanges xwc;
DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y);
+ if(dpy==NULL) {
+ _throwNewRuntimeException(NULL, env, "invalid display connection..\n");
+ return;
+ }
+ XLockDisplay(dpy) ;
+
xwc.x=x;
xwc.y=y;
XConfigureWindow(dpy, w, CWX|CWY, &xwc);
XSync(dpy, False);
+
+ XUnlockDisplay(dpy) ;
}