diff options
author | Sven Gothel <[email protected]> | 2011-09-25 04:38:59 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-09-25 04:38:59 +0200 |
commit | e5ab975727134d8249277f4df707b2b14a7788f3 (patch) | |
tree | 296ff9712f24df60c6840f169313ec87c2bfeff0 /src/newt/classes/com/jogamp | |
parent | b72bedc93e4dca6d3c55cae0cc811cb4baac13e0 (diff) |
NEWT/JOGL: MacOSX Update
Feature related:
- Added always-on-top
- Added translucency
- Child Window Position
- AWT parent: manual traverse up the tree and calc position on screen
(Problem: the parent view rect is not at the proper position,
but covers the whole frame)
EDTUtil related:
- Works now w/ AWT ot headless (again)
- OSX native JNI callbacks gathering JNIEnv properly
and attaches/detaches thread.
- AWT case: using AWT-Event which properly dispatches our cocoa events
- MainThread (headless) case: Fork off thread w/ main class
and kick off NSApp run().
This leads to same behavior as w/ AWT case.
- Using DefaultEDTUtil
- Cleanup MainThread (implements EDTUtil)
- Currently not used as EDTUtil (osx), just as launcher
- Removed EDTUtil impl code, reuse DefaultEDTUtil
- Cleanup AWTEDTUtil (implements EDTUtil)
- Currently not used as EDTUtil (osx)
Diffstat (limited to 'src/newt/classes/com/jogamp')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/util/MainThread.java | 331 |
1 files changed, 57 insertions, 274 deletions
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index 07c58d731..f74845afc 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -41,22 +41,19 @@ import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; import java.security.AccessController; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.NativeWindowFactory; +import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.common.util.RunnableTask; import com.jogamp.newt.Display; + import jogamp.newt.Debug; +import jogamp.newt.DefaultEDTUtil; import jogamp.newt.NEWTJNILibLoader; -import jogamp.newt.driver.awt.AWTEDTUtil; /** * NEWT Utility class MainThread<P> @@ -92,26 +89,26 @@ import jogamp.newt.driver.awt.AWTEDTUtil; * Which starts 4 threads, each with a window and OpenGL rendering.<br> */ public class MainThread implements EDTUtil { - private static final AccessControlContext localACC = AccessController.getContext(); + private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay"; /** if true, use the main thread EDT, otherwise AWT's EDT */ - public static final boolean HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() || - Debug.getBooleanProperty("newt.MainThread.force", true, localACC); + public static final boolean HINT_USE_MAIN_THREAD; + + static { + final AccessControlContext localACC = AccessController.getContext(); + Platform.initSingleton(); + NativeWindowFactory.initSingleton(true); + NEWTJNILibLoader.loadNEWT(); + HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() || + Debug.getBooleanProperty("newt.MainThread.force", true, localACC); + } + public static boolean useMainThread = false; protected static final boolean DEBUG = Debug.debug("MainThread"); private static final MainThread singletonMainThread = new MainThread(); // one singleton MainThread - private static boolean isExit=false; - private static volatile boolean isRunning=false; - private static final Object edtLock=new Object(); - private static boolean shouldStop; - private static ArrayList<RunnableTask> tasks; - private static Thread mainThread; - - private static Timer pumpMessagesTimer=null; - private static TimerTask pumpMessagesTimerTask=null; private static final Map<Display, Runnable> pumpMessageDisplayMap = new HashMap<Display, Runnable>(); static class MainAction extends Thread { @@ -127,11 +124,7 @@ public class MainThread implements EDTUtil { @Override public void run() { - if ( useMainThread ) { - // we have to start first to provide the service .. - singletonMainThread.waitUntilRunning(); - } - + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start"); // start user app .. try { Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader()); @@ -166,15 +159,20 @@ public class MainThread implements EDTUtil { } private static MainAction mainAction; + private static EDTUtil internalEDT; + /** Your new java application main entry, which pipelines your application */ public static void main(String[] args) { useMainThread = HINT_USE_MAIN_THREAD; + final Platform.OSType osType = Platform.getOSType(); + final boolean isMacOSX = osType == Platform.OSType.MACOS; + if(DEBUG) { System.err.println("MainThread.main(): "+Thread.currentThread().getName()+ ", useMainThread "+ useMainThread + ", HINT_USE_MAIN_THREAD "+ HINT_USE_MAIN_THREAD + - ", isAWTAvailable " + NativeWindowFactory.isAWTAvailable()); + ", isAWTAvailable " + NativeWindowFactory.isAWTAvailable() + ", ostype "+osType+", isMacOSX "+isMacOSX); } if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) { @@ -191,25 +189,34 @@ public class MainThread implements EDTUtil { System.arraycopy(args, 1, mainClassArgs, 0, args.length-1); } - NEWTJNILibLoader.loadNEWT(); - mainAction = new MainAction(mainClassName, mainClassArgs); - if(NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) { - ReflectionUtil.callStaticMethod("jogamp.newt.macosx.MacDisplay", "initSingleton", + if(isMacOSX) { + ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "initSingleton", null, null, MainThread.class.getClassLoader()); } if ( useMainThread ) { - shouldStop = false; - tasks = new ArrayList<RunnableTask>(); - mainThread = Thread.currentThread(); + final Thread current = Thread.currentThread(); + internalEDT = new DefaultEDTUtil(current.getThreadGroup(), "MainThread", new Runnable() { + public void run() { dispatchMessages(); } }); + if(DEBUG) System.err.println("MainThread - run: "+internalEDT.toString()); + internalEDT.start(); // forever ! + // dispatch user's main thread .. mainAction.start(); - - // do our main thread task scheduling - singletonMainThread.run(); + + if(isMacOSX) { + try { + if(DEBUG) System.err.println("MainThread - runNSApp"); + ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "runNSApplication", + null, null, MainThread.class.getClassLoader()); + } catch (Exception e) { + e.printStackTrace(); + } + } + if(DEBUG) System.err.println("MainThread - wait until last non daemon thread ends ..."); } else { // run user's main in this thread mainAction.run(); @@ -227,273 +234,49 @@ public class MainThread implements EDTUtil { } public static void addPumpMessage(Display dpy, Runnable pumpMessage) { - if(DEBUG) { - System.err.println("MainThread.addPumpMessage(): "+Thread.currentThread().getName()+ - " - dpy "+dpy+", USE_MAIN_THREAD " + useMainThread + - " - hasAWT " + NativeWindowFactory.isAWTAvailable() ); - } - if(!useMainThread && !NativeWindowFactory.isAWTAvailable()) { - throw new RuntimeException("!USE_MAIN_THREAD and no AWT available"); - } - synchronized (pumpMessageDisplayMap) { - if(!useMainThread && null == pumpMessagesTimer) { - // AWT pump messages .. MAIN_THREAD uses main thread - pumpMessagesTimer = new Timer(); - pumpMessagesTimerTask = new TimerTask() { - public void run() { - synchronized(pumpMessageDisplayMap) { - for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) { - i.next().run(); - } - } - } - }; - pumpMessagesTimer.scheduleAtFixedRate(pumpMessagesTimerTask, 0, defaultEDTPollGranularity); - } pumpMessageDisplayMap.put(dpy, pumpMessage); } } - final public void reset() { - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.getSingleton().reset(); + private static void dispatchMessages() { + synchronized(pumpMessageDisplayMap) { + for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) { + i.next().run(); + } } - // nop + } + + final public void reset() { + // nop: ALWAYS RUNNING } final public void start() { - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.getSingleton().start(); - } - // nop + // nop: ALWAYS RUNNING } final public boolean isCurrentThreadEDT() { - if(NativeWindowFactory.isAWTAvailable()) { - return AWTEDTUtil.getSingleton().isCurrentThreadEDT(); - } - return isRunning() && mainThread == Thread.currentThread() ; + return internalEDT.isCurrentThreadEDT(); } final public boolean isRunning() { - if( useMainThread ) { - return isRunning; - } - return true; // AWT is always running + return true; // ALWAYS RUNNING } final public void invokeStop(Runnable r) { - invokeImpl(true, r, true); + internalEDT.invoke(true, r); // ALWAYS RUNNING } final public void invoke(boolean wait, Runnable r) { - invokeImpl(wait, r, false); - } - - private void invokeImpl(boolean wait, Runnable task, boolean stop) { - if(task == null) { - return; - } - - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.getSingleton().invokeImpl(wait, task, stop); - return; - } - - // if this main thread is not being used or - // if this is already the main thread .. just execute. - // FIXME: start if not started .. sync logic with DefaultEDTUtil!!! - if( !isRunning() || mainThread == Thread.currentThread() ) { - task.run(); - return; - } - - Throwable throwable = null; - RunnableTask rTask = null; - Object rTaskLock = new Object(); - synchronized(rTaskLock) { - synchronized(edtLock) { - if( shouldStop ) { - // drop task .. - if(DEBUG) { - System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+this); - Thread.dumpStack(); - } - return; - } - // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+tasks.size()+", task: "+task); - // Thread.dumpStack(); - if(stop) { - shouldStop = true; - if(DEBUG) System.err.println("MainThread.stop(): "+Thread.currentThread().getName()+" start"); - } - if( isCurrentThreadEDT() ) { - task.run(); - wait = false; // running in same thread (EDT) -> no wait - if(stop && tasks.size()>0) { - System.err.println("Warning: EDT about (2) to stop, having remaining tasks: "+tasks.size()+" - "+this); - if(DEBUG) { - Thread.dumpStack(); - } - } - } else { - synchronized(tasks) { - start(); // start if not started yet and !shouldStop - wait = wait && isRunning(); - rTask = new RunnableTask(task, - wait ? rTaskLock : null, - true /* always catch and report Exceptions, don't disturb EDT */); - if(stop) { - rTask.setAttachment(new Boolean(true)); // mark final task - } - // append task .. - tasks.add(rTask); - tasks.notifyAll(); - } - } - } - if( wait ) { - try { - rTaskLock.wait(); // free lock, allow execution of rTask - } catch (InterruptedException ie) { - throwable = ie; - } - if(null==throwable) { - throwable = rTask.getThrowable(); - } - if(null!=throwable) { - if(throwable instanceof NativeWindowException) { - throw (NativeWindowException)throwable; - } - throw new RuntimeException(throwable); - } - } - } - if(DEBUG && stop) { - System.err.println(Thread.currentThread()+": EDT signal STOP X edt: "+this); - } + internalEDT.invoke(wait, r); } final public void waitUntilIdle() { - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.getSingleton().waitUntilIdle(); - } + internalEDT.waitUntilIdle(); } final public void waitUntilStopped() { - if(NativeWindowFactory.isAWTAvailable()) { - AWTEDTUtil.getSingleton().waitUntilStopped(); - } - } - - private void waitUntilRunning() { - synchronized(edtLock) { - if(isExit) return; - - while(!isRunning) { - try { - edtLock.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - public void run() { - if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName()); - synchronized(edtLock) { - isRunning = true; - edtLock.notifyAll(); - } - - RuntimeException error = null; - try { - do { - // event dispatch - if(!shouldStop) { - synchronized(pumpMessageDisplayMap) { - for(Iterator<Runnable> i = pumpMessageDisplayMap.values().iterator(); i.hasNext(); ) { - i.next().run(); - } - } - } - // wait for something todo .. - Runnable task = null; - synchronized(tasks) { - // wait for tasks - if(!shouldStop && tasks.size()==0) { - try { - tasks.wait(defaultEDTPollGranularity); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - // execute one task, if available - if(tasks.size()>0) { - task = tasks.remove(0); - tasks.notifyAll(); - } - } - if(null!=task) { - // Exceptions are always catched, see Runnable creation above - task.run(); - } - } while(!shouldStop) ; - } catch (Throwable t) { - // handle errors .. - shouldStop = true; - if(t instanceof RuntimeException) { - error = (RuntimeException) t; - } else { - error = new RuntimeException("Within EDT", t); - } - } finally { - if(DEBUG) { - RunnableTask rt = ( tasks.size() > 0 ) ? tasks.get(0) : null ; - System.err.println(/* getName()+*/"EDT run() END, tasks: "+tasks.size()+", "+rt+", "+error); - } - synchronized(edtLock) { - if(null==error) { - synchronized(tasks) { - // drain remaining tasks (stop not on EDT), - // while having tasks and no previous-task, or previous-task is non final - RunnableTask task = null; - while ( ( null == task || task.getAttachment() == null ) && tasks.size() > 0 ) { - task = tasks.remove(0); - task.run(); - tasks.notifyAll(); - } - if(DEBUG) { - if(null!=task && task.getAttachment()==null) { - System.err.println("Warning: EDT exit: Last task Not Final: "+tasks.size()+", "+task); - } else if(tasks.size()>0) { - System.err.println("Warning: EDT exit: Remaining tasks Post Final: "+tasks.size()); - } - Thread.dumpStack(); - } - } - } - isRunning = !shouldStop; - if(!isRunning) { - edtLock.notifyAll(); - } - } - if(DEBUG) { - System.err.println("EDT run() EXIT "+ error); - } - if(null!=error) { - throw error; - } - } // finally - - if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName()+" fin"); - synchronized(edtLock) { - isRunning = false; - isExit = true; - edtLock.notifyAll(); - } + // nop: ALWAYS RUNNING } } |