diff options
author | Sven Gothel <[email protected]> | 2009-06-17 13:26:29 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2009-06-17 13:26:29 +0000 |
commit | a92906bcb4ce4746f291d40a736949ec8476de61 (patch) | |
tree | 49708922895aa07bdc72b0513bb5e90f63ecedb2 | |
parent | 802288f8964affbda3460eea52df3d241ae3036a (diff) |
- Add: GLProfile.get(name) return default if name=="GL" as well (or if null)
- Add: NEWT pumpMessages/dispatchMessages
- Handled by the Display implementation for all windows
- Windows .. OK
- MacOSX .. OK
- X11 .. OK
- Added Atom Property handling to attach java window object to window
- Removed the eventMask for dispatching messages,
since dispatching is for all windows now.
(Wasn't impl. for all platforms anyways)
- All init static code will funnel in the Display.initSingletion(),
to ensure a proper init order for all platforms.
- Display creation is unique for (name,thread).
Handling a TLS mapping of display-names to Displays.
- GLWindow: autoSwapBufferMode and eventHandlerMode are static members
- Tested with experimental tagged
GLWindow.setRunPumpMessages()/runCurrentThreadPumpMessage(),
1 thread - 4 windows, etc ..
java demos.es2.RedSquare -1thread -onepump -GL2 -GL2 -GL2 -GL2
No benefit ..
However .. the implementation is more correct now,
due to the display/current-thread message pumping.
- Fix: Window.sendMouseEvent() bounds check
- Fix: MacWindow has proper nsView locking now,
local to the window instance. locked in lockSurface
besides general window manipulation.
- Fix: JAWT utilized JAWTUtil.init() to
init libraries - NativeLibLoaderBase.loadNativeWindow("awt")
call was missing. (Visible on MacOSX + AWT)
- Fix: GLXUtil proper locking
- Fix: X11Util proper locking
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1976 232f8b59-042b-4e1e-8c03-345bb8c30851
28 files changed, 1548 insertions, 934 deletions
diff --git a/make/config/nativewindow/jawt-CustomJavaCode.java b/make/config/nativewindow/jawt-CustomJavaCode.java index f1ef91075..b92e5a983 100755 --- a/make/config/nativewindow/jawt-CustomJavaCode.java +++ b/make/config/nativewindow/jawt-CustomJavaCode.java @@ -5,7 +5,7 @@ public static JAWT getJAWT() { if (jawt == null) { synchronized (JAWT.class) { if (jawt == null) { - JAWTNativeLibLoader.loadAWTImpl(); + JAWTUtil.init(); // Workaround for 4845371. // Make sure the first reference to the JNI GetDirectBufferAddress is done // from a privileged context so the VM's internal class lookups will succeed. diff --git a/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java index b8968ee99..8ab99ac0a 100644 --- a/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/com/sun/opengl/impl/x11/glx/GLXUtil.java @@ -51,40 +51,44 @@ public class GLXUtil { // Display connection for use by visual selection algorithm and by all offscreen surfaces private static boolean multisampleAvailable=false; - private static boolean isInit=false; + private static volatile boolean isInit=false; - private static void init() { + private static synchronized void init() { if (!isInit) { - NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); - try { - long staticDisplay = X11Util.getStaticDefaultDisplay(); - if(staticDisplay!=0) { - if (DEBUG) { - long display = staticDisplay; - int screen = X11Lib.DefaultScreen(display); - System.err.println("!!! GLX server vendor : " + - GLX.glXQueryServerString(display, screen, GLX.GLX_VENDOR)); - System.err.println("!!! GLX server version: " + - GLX.glXQueryServerString(display, screen, GLX.GLX_VERSION)); - System.err.println("!!! GLX client vendor : " + - GLX.glXGetClientString(display, GLX.GLX_VENDOR)); - System.err.println("!!! GLX client version: " + - GLX.glXGetClientString(display, GLX.GLX_VERSION)); + synchronized (GLXUtil.class) { + if (!isInit) { + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + long staticDisplay = X11Util.getStaticDefaultDisplay(); + if(staticDisplay!=0) { + if (DEBUG) { + long display = staticDisplay; + int screen = X11Lib.DefaultScreen(display); + System.err.println("!!! GLX server vendor : " + + GLX.glXQueryServerString(display, screen, GLX.GLX_VENDOR)); + System.err.println("!!! GLX server version: " + + GLX.glXQueryServerString(display, screen, GLX.GLX_VERSION)); + System.err.println("!!! GLX client vendor : " + + GLX.glXGetClientString(display, GLX.GLX_VENDOR)); + System.err.println("!!! GLX client version: " + + GLX.glXGetClientString(display, GLX.GLX_VERSION)); + } + String vendor = GLX.glXGetClientString(staticDisplay, GLX.GLX_VENDOR); + if (vendor != null && vendor.startsWith("ATI")) { + isVendorATI = true; + } + String exts = GLX.glXGetClientString(staticDisplay, GLX.GLX_EXTENSIONS); + if (exts != null) { + multisampleAvailable = (exts.indexOf("GLX_ARB_multisample") >= 0); + } + isInit=true; + } else { + throw new GLException("Unable to open default display, needed for visual selection and offscreen surface handling"); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } - String vendor = GLX.glXGetClientString(staticDisplay, GLX.GLX_VENDOR); - if (vendor != null && vendor.startsWith("ATI")) { - isVendorATI = true; - } - String exts = GLX.glXGetClientString(staticDisplay, GLX.GLX_EXTENSIONS); - if (exts != null) { - multisampleAvailable = (exts.indexOf("GLX_ARB_multisample") >= 0); - } - isInit=true; - } else { - throw new GLException("Unable to open default display, needed for visual selection and offscreen surface handling"); } - } finally { - NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } } } diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index 57f4fb46a..385006b75 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -104,13 +104,15 @@ public class GLProfile implements Cloneable { /** Returns a GLProfile object. * Verfifies the given profile and chooses an apropriate implementation. + * A generic value of <code>null</code> or <code>GL</code> will result in + * the default profile. * * @throws GLException if no implementation for the given profile is found. */ public static final GLProfile get(String profile) throws GLException { - if(null==profile) return getDefault(); + if(null==profile || profile.equals("GL")) return getDefault(); GLProfile glProfile = (GLProfile) mappedProfiles.get(profile); if(null==glProfile) { throw new GLException("No implementation for profile "+profile+" available"); diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/jawt/JAWTUtil.java b/src/nativewindow/classes/com/sun/nativewindow/impl/jawt/JAWTUtil.java index ae606a790..20e8cf966 100644 --- a/src/nativewindow/classes/com/sun/nativewindow/impl/jawt/JAWTUtil.java +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/jawt/JAWTUtil.java @@ -43,21 +43,28 @@ import javax.media.nativewindow.*; import java.awt.GraphicsEnvironment; public class JAWTUtil { - static { - JAWTNativeLibLoader.loadAWTImpl(); - NativeLibLoaderBase.loadNativeWindow("awt"); - } - - // See whether we're running in headless mode - private static boolean headlessMode; static { + JAWTNativeLibLoader.loadAWTImpl(); + NativeLibLoaderBase.loadNativeWindow("awt"); + lockedStack = null; headlessMode = GraphicsEnvironment.isHeadless(); } + // See whether we're running in headless mode + private static final boolean headlessMode; + private static Exception lockedStack; + // Just a hook to let this class being initialized, + // ie loading the native libraries .. + public static void init() { } + + public static boolean isHeadlessMode() { + return headlessMode; + } + public static synchronized void lockToolkit() throws NativeWindowException { if (null!=lockedStack) { lockedStack.printStackTrace(); diff --git a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java index 731bd3caf..38d0fb73d 100644 --- a/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java +++ b/src/nativewindow/classes/com/sun/nativewindow/impl/x11/X11Util.java @@ -73,18 +73,23 @@ public class X11Util { private static ThreadLocal currentDisplayAssociation = new ThreadLocal(); - private static long staticDefaultDisplay=0; + private static volatile long staticDefaultDisplay=0; private static boolean staticDefaultDisplayXineramaEnable=false; private static long fetchStaticDefaultDisplay() { if(0==staticDefaultDisplay) { synchronized (X11Util.class) { if(0==staticDefaultDisplay) { - staticDefaultDisplay = X11Lib.XOpenDisplay(null); - if(0==staticDefaultDisplay) { - throw new NativeWindowException("Unable to create a static default display connection"); + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + staticDefaultDisplay = X11Lib.XOpenDisplay(null); + if(0==staticDefaultDisplay) { + throw new NativeWindowException("Unable to create a static default display connection"); + } + staticDefaultDisplayXineramaEnable = X11Lib.XineramaEnabled(staticDefaultDisplay); + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } - staticDefaultDisplayXineramaEnable = X11Lib.XineramaEnabled(staticDefaultDisplay); } } } @@ -109,15 +114,20 @@ public class X11Util { public static long getThreadLocalDefaultDisplay() { Long dpyL = (Long) currentDisplayAssociation.get(); if(null==dpyL) { - long dpy = X11Lib.XOpenDisplay(null); - if(0==dpy) { - throw new NativeWindowException("Unable to create a default display connection on Thread "+Thread.currentThread().getName()); - } - dpyL = new Long(dpy); - currentDisplayAssociation.set( dpyL ); - if(DEBUG) { - Exception e = new Exception("Created new TLS display connection 0x"+Long.toHexString(dpy)+" for thread "+Thread.currentThread().getName()); - e.printStackTrace(); + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + long dpy = X11Lib.XOpenDisplay(null); + if(0==dpy) { + throw new NativeWindowException("Unable to create a default display connection on Thread "+Thread.currentThread().getName()); + } + dpyL = new Long(dpy); + currentDisplayAssociation.set( dpyL ); + if(DEBUG) { + Exception e = new Exception("Created new TLS display connection 0x"+Long.toHexString(dpy)+" for thread "+Thread.currentThread().getName()); + e.printStackTrace(); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); } } return dpyL.longValue(); diff --git a/src/newt/classes/com/sun/javafx/newt/Display.java b/src/newt/classes/com/sun/javafx/newt/Display.java index b5d3c8520..5032477c9 100755 --- a/src/newt/classes/com/sun/javafx/newt/Display.java +++ b/src/newt/classes/com/sun/javafx/newt/Display.java @@ -34,8 +34,11 @@ package com.sun.javafx.newt; import javax.media.nativewindow.*; +import com.sun.javafx.newt.impl.Debug; +import java.util.*; -public abstract class Display { +public abstract class Display implements Runnable { + public static final boolean DEBUG = Debug.debug("Display"); private static Class getDisplayClass(String type) throws ClassNotFoundException @@ -57,14 +60,93 @@ public abstract class Display { return displayClass; } + private static ThreadLocal currentDisplayMap = new ThreadLocal(); + + /** Returns the thread local display map */ + public static Map getCurrentDisplayMap() { + Map displayMap = (Map) currentDisplayMap.get(); + if(null==displayMap) { + displayMap = new HashMap(); + currentDisplayMap.set( displayMap ); + } + return displayMap; + } + + /** maps the given display to the thread local display map + * and notifies all threads synchronized to this display map. */ + protected static Display setCurrentDisplay(Display display) { + Map displayMap = getCurrentDisplayMap(); + Display oldDisplay = null; + synchronized(displayMap) { + String name = display.getName(); + if(null==name) name="nil"; + oldDisplay = (Display) displayMap.put(name, display); + displayMap.notifyAll(); + } + return oldDisplay; + } + + /** removes the mapping of the given name from the thread local display map + * and notifies all threads synchronized to this display map. */ + protected static Display removeCurrentDisplay(String name) { + if(null==name) name="nil"; + Map displayMap = getCurrentDisplayMap(); + Display oldDisplay = null; + synchronized(displayMap) { + oldDisplay = (Display) displayMap.remove(name); + displayMap.notifyAll(); + } + return oldDisplay; + } + + /** Returns the thread local display mapped to the given name */ + public static Display getCurrentDisplay(String name) { + if(null==name) name="nil"; + Map displayMap = getCurrentDisplayMap(); + Display display = (Display) displayMap.get(name); + return display; + } + + private 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()); + for(int j=0; i.hasNext(); j++) { + Map.Entry entry = (Map.Entry) i.next(); + System.err.println(" ["+j+"] "+entry.getKey()+" -> "+entry.getValue()); + } + } + + /** Returns the thread local display collection */ + public static Collection getCurrentDisplays() { + return getCurrentDisplayMap().values(); + } + + /** Make sure to reuse a Display with the same name */ protected static Display create(String type, String name) { try { - Class displayClass = getDisplayClass(type); - Display display = (Display) displayClass.newInstance(); - display.name=name; - display.createNative(); - if(null==display.aDevice) { - throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); + Display display = getCurrentDisplay(name); + if(null==display) { + Class displayClass = getDisplayClass(type); + display = (Display) displayClass.newInstance(); + display.name=name; + display.refCount=1; + 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()); + } + } else { + synchronized(display) { + display.refCount++; + if(DEBUG) { + System.err.println("Display.create("+name+") REUSE: refCount "+display.refCount+", "+display+" "+Thread.currentThread().getName()); + } + } } return display; } catch (Exception e) { @@ -73,7 +155,18 @@ public abstract class Display { } public synchronized void destroy() { - closeNative(); + refCount--; + if(0==refCount) { + removeCurrentDisplay(name); + if(DEBUG) { + System.err.println("Display.destroy("+name+") REMOVE: "+this+" "+Thread.currentThread().getName()); + } + closeNative(); + } else { + if(DEBUG) { + System.err.println("Display.destroy("+name+") KEEP: refCount "+refCount+", "+this+" "+Thread.currentThread().getName()); + } + } } protected static Display wrapHandle(String type, String name, AbstractGraphicsDevice aDevice) { @@ -103,7 +196,36 @@ public abstract class Display { 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 String toString() { + return "NEWT-Display["+name+", refCount "+refCount+", "+aDevice+"]"; + } + + protected abstract void dispatchMessages(); + 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 new file mode 100644 index 000000000..8f02148a2 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/DisplayActionThread.java @@ -0,0 +1,118 @@ +/* + * 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/Window.java b/src/newt/classes/com/sun/javafx/newt/Window.java index 68cb97834..36eafd32d 100755 --- a/src/newt/classes/com/sun/javafx/newt/Window.java +++ b/src/newt/classes/com/sun/javafx/newt/Window.java @@ -137,27 +137,6 @@ public abstract class Window implements NativeWindow return screen; } - /** - * eventMask is a bitfield of EventListener event flags - */ - public void pumpMessages(int eventMask) { - if(this.eventMask!=eventMask && eventMask>0) { - this.eventMask=eventMask; - eventMask*=-1; - } - dispatchMessages(eventMask); - } - - public void pumpMessages() { - int em = 0; - if(windowListeners.size()>0) em |= EventListener.WINDOW; - if(mouseListeners.size()>0) em |= EventListener.MOUSE; - if(keyListeners.size()>0) em |= EventListener.KEY; - pumpMessages(em); - } - - protected abstract void dispatchMessages(int eventMask); - public String toString() { StringBuffer sb = new StringBuffer(); @@ -438,6 +417,9 @@ public abstract class Window implements NativeWindow protected void sendMouseEvent(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.out.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java index 099125630..19f3ed1a8 100644 --- a/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java @@ -33,10 +33,12 @@ package com.sun.javafx.newt.awt; -import java.awt.*; -import com.sun.javafx.newt.*; +import java.awt.event.*; +import com.sun.javafx.newt.Display; +import com.sun.javafx.newt.Window; import javax.media.nativewindow.*; import javax.media.nativewindow.awt.*; +import java.util.*; public class AWTDisplay extends Display { public AWTDisplay() { @@ -51,4 +53,116 @@ public class AWTDisplay extends Display { } protected void closeNative() { } + + public void dispatchMessages() { + AWTEventWrapper w; + do { + synchronized(this) { + if (!events.isEmpty()) { + w = (AWTEventWrapper) events.removeFirst(); + } else { + w = null; + } + } + if (w != null) { + switch (w.getType()) { + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED: + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED: + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY: + w.getWindow().sendWindowEvent(w.getType()); + break; + + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_CLICKED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_WHEEL_MOVED: + { + MouseEvent e = (MouseEvent) w.getEvent(); + int rotation = 0; + if (e instanceof MouseWheelEvent) { + rotation = ((MouseWheelEvent)e).getWheelRotation(); + } + w.getWindow().sendMouseEvent(w.getType(), convertModifiers(e), + e.getX(), e.getY(), convertButton(e), + rotation); + } + break; + + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED: + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED: + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED: + { + KeyEvent e = (KeyEvent) w.getEvent(); + w.getWindow().sendKeyEvent(w.getType(), convertModifiers(e), + e.getKeyCode(), e.getKeyChar()); + } + break; + + default: + throw new NativeWindowException("Unknown event type " + w.getType()); + } + if(Window.DEBUG_MOUSE_EVENT) { + System.out.println("dispatchMessages: "+w.getWindow()+" in event:"+w.getEvent()); + } + } + } while (w != null); + } + + protected void enqueueEvent(AWTWindow w, int type, InputEvent e) { + AWTEventWrapper wrapper = new AWTEventWrapper(w, type, e); + synchronized(this) { + events.add(wrapper); + } + } + + private LinkedList/*<AWTEventWrapper>*/ events = new LinkedList(); + + static class AWTEventWrapper { + AWTWindow window; + int type; + InputEvent e; + + AWTEventWrapper(AWTWindow w, int type, InputEvent e) { + this.window = w; + this.type = type; + this.e = e; + } + + public AWTWindow getWindow() { + return window; + } + + public int getType() { + return type; + } + + public InputEvent getEvent() { + return e; + } + } + + private static int convertModifiers(InputEvent e) { + int newtMods = 0; + int mods = e.getModifiers(); + if ((mods & InputEvent.SHIFT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.SHIFT_MASK; + if ((mods & InputEvent.CTRL_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.CTRL_MASK; + if ((mods & InputEvent.META_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.META_MASK; + if ((mods & InputEvent.ALT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_MASK; + if ((mods & InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_GRAPH_MASK; + return newtMods; + } + + private static int convertButton(MouseEvent e) { + switch (e.getButton()) { + case MouseEvent.BUTTON1: return com.sun.javafx.newt.MouseEvent.BUTTON1; + case MouseEvent.BUTTON2: return com.sun.javafx.newt.MouseEvent.BUTTON2; + case MouseEvent.BUTTON3: return com.sun.javafx.newt.MouseEvent.BUTTON3; + } + return 0; + } + } diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java index 3742a0e57..a425386a3 100644 --- a/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java @@ -63,7 +63,6 @@ public class AWTWindow extends Window { private Frame frame; private AWTCanvas canvas; - private LinkedList/*<AWTEventWrapper>*/ events = new LinkedList(); // non fullscreen dimensions .. private int nfs_width, nfs_height, nfs_x, nfs_y; @@ -80,13 +79,15 @@ public class AWTWindow extends Window { protected void createNative(final Capabilities caps) { + final AWTWindow awtWindow = this; + runOnEDT(true, new Runnable() { public void run() { frame = new Frame(getTitle()); frame.setUndecorated(isUndecorated()); frame.setLayout(new BorderLayout()); canvas = new AWTCanvas(caps); - Listener listener = new Listener(); + Listener listener = new Listener(awtWindow); canvas.addMouseListener(listener); canvas.addMouseMotionListener(listener); canvas.addKeyListener(listener); @@ -94,8 +95,8 @@ public class AWTWindow extends Window { frame.add(canvas, BorderLayout.CENTER); frame.setSize(width, height); frame.setLocation(x, y); - frame.addComponentListener(new MoveListener()); - frame.addWindowListener(new WindowEventListener()); + frame.addComponentListener(new MoveListener(awtWindow)); + frame.addWindowListener(new WindowEventListener(awtWindow)); } }); } @@ -216,84 +217,17 @@ public class AWTWindow extends Window { return canvas; } - public void dispatchMessages(int eventMask) { - AWTEventWrapper w; - do { - synchronized(this) { - if (!events.isEmpty()) { - w = (AWTEventWrapper) events.removeFirst(); - } else { - w = null; - } - } - if (w != null) { - switch (w.getType()) { - case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED: - case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED: - case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY: - if ((eventMask & com.sun.javafx.newt.EventListener.WINDOW) != 0) { - sendWindowEvent(w.getType()); - } - break; - - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_CLICKED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED: - case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_WHEEL_MOVED: - if ((eventMask & com.sun.javafx.newt.EventListener.MOUSE) != 0) { - MouseEvent e = (MouseEvent) w.getEvent(); - int rotation = 0; - if (e instanceof MouseWheelEvent) { - rotation = ((MouseWheelEvent)e).getWheelRotation(); - } - sendMouseEvent(w.getType(), convertModifiers(e), - e.getX(), e.getY(), convertButton(e), - rotation); - } - break; - - case com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED: - case com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED: - case com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED: - if ((eventMask & com.sun.javafx.newt.EventListener.KEY) != 0) { - KeyEvent e = (KeyEvent) w.getEvent(); - sendKeyEvent(w.getType(), convertModifiers(e), - e.getKeyCode(), e.getKeyChar()); - } - break; - - default: - throw new NativeWindowException("Unknown event type " + w.getType()); - } - if(Window.DEBUG_MOUSE_EVENT) { - System.out.println("dispatchMessages: in event:"+w.getEvent()); - } - } - } while (w != null); + protected void sendWindowEvent(int eventType) { + super.sendWindowEvent(eventType); } - private static int convertModifiers(InputEvent e) { - int newtMods = 0; - int mods = e.getModifiers(); - if ((mods & InputEvent.SHIFT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.SHIFT_MASK; - if ((mods & InputEvent.CTRL_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.CTRL_MASK; - if ((mods & InputEvent.META_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.META_MASK; - if ((mods & InputEvent.ALT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_MASK; - if ((mods & InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_GRAPH_MASK; - return newtMods; + protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + super.sendKeyEvent(eventType, modifiers, keyCode, keyChar); } - private static int convertButton(MouseEvent e) { - switch (e.getButton()) { - case MouseEvent.BUTTON1: return com.sun.javafx.newt.MouseEvent.BUTTON1; - case MouseEvent.BUTTON2: return com.sun.javafx.newt.MouseEvent.BUTTON2; - case MouseEvent.BUTTON3: return com.sun.javafx.newt.MouseEvent.BUTTON3; - } - return 0; + protected void sendMouseEvent(int eventType, int modifiers, + int x, int y, int button, int rotation) { + super.sendMouseEvent(eventType, modifiers, x, y, button, rotation); } private static void runOnEDT(boolean wait, Runnable r) { @@ -312,43 +246,26 @@ public class AWTWindow extends Window { } } - private void enqueueEvent(int type, InputEvent e) { - AWTEventWrapper wrapper = new AWTEventWrapper(type, e); - synchronized(this) { - events.add(wrapper); - } - } - private static final int WINDOW_EVENT = 1; private static final int KEY_EVENT = 2; private static final int MOUSE_EVENT = 3; - static class AWTEventWrapper { - int type; - InputEvent e; - - AWTEventWrapper(int type, InputEvent e) { - this.type = type; - this.e = e; - } - - public int getType() { - return type; - } + class MoveListener implements ComponentListener { + private AWTWindow window; + private AWTDisplay display; - public InputEvent getEvent() { - return e; + public MoveListener(AWTWindow w) { + window = w; + display = (AWTDisplay)window.getScreen().getDisplay(); } - } - class MoveListener implements ComponentListener { public void componentResized(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { x = frame.getX(); y = frame.getY(); - enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED, null); + display.enqueueEvent(window, com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED, null); } public void componentShown(ComponentEvent e) { @@ -360,10 +277,18 @@ public class AWTWindow extends Window { } class Listener implements ComponentListener, MouseListener, MouseMotionListener, KeyListener { + private AWTWindow window; + private AWTDisplay display; + + public Listener(AWTWindow w) { + window = w; + display = (AWTDisplay)window.getScreen().getDisplay(); + } + public void componentResized(ComponentEvent e) { width = canvas.getWidth(); height = canvas.getHeight(); - enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED, null); + display.enqueueEvent(window, com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED, null); } public void componentMoved(ComponentEvent e) { @@ -381,49 +306,57 @@ public class AWTWindow extends Window { } public void mouseEntered(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED, e); } public void mouseExited(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED, e); } public void mousePressed(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED, e); } public void mouseReleased(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED, e); } public void mouseMoved(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED, e); } public void mouseDragged(MouseEvent e) { - enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED, e); + display.enqueueEvent(window, com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED, e); } public void keyPressed(KeyEvent e) { - enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED, e); + display.enqueueEvent(window, com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED, e); } public void keyReleased(KeyEvent e) { - enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED, e); + display.enqueueEvent(window, com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED, e); } public void keyTyped(KeyEvent e) { - enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED, e); + display.enqueueEvent(window, com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED, e); } } class WindowEventListener implements WindowListener { + private AWTWindow window; + private AWTDisplay display; + + public WindowEventListener(AWTWindow w) { + window = w; + display = (AWTDisplay)window.getScreen().getDisplay(); + } + public void windowActivated(WindowEvent e) { } public void windowClosed(WindowEvent e) { } public void windowClosing(WindowEvent e) { - enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY, null); + display.enqueueEvent(window, com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY, null); } public void windowDeactivated(WindowEvent e) { } diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java index 29b7151f4..63b7fe78c 100755 --- a/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java @@ -33,17 +33,55 @@ package com.sun.javafx.newt.macosx; -import com.sun.javafx.newt.*; import javax.media.nativewindow.*; import javax.media.nativewindow.macosx.*; +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import com.sun.javafx.newt.util.MainThread; public class MacDisplay extends Display { + static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + + NativeLibLoader.loadNEWT(); + + if(!initNSApplication()) { + throw new NativeWindowException("Failed to initialize native Application hook"); + } + if(!MacWindow.initIDs()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + if(DEBUG) System.out.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName()); + } + public MacDisplay() { } + class DispatchAction implements Runnable { + public void run() { + dispatchMessages0(); + } + } + private DispatchAction dispatchAction = new DispatchAction(); + + public void dispatchMessages() { + MainThread.invoke(false, dispatchAction); + } + protected void createNative() { aDevice = new MacOSXGraphicsDevice(); } protected void closeNative() { } + + private static native boolean initNSApplication(); + protected native void dispatchMessages0(); } + diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java index 06ef8aacd..8983b8803 100755 --- a/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java @@ -37,14 +37,20 @@ import com.sun.javafx.newt.*; import javax.media.nativewindow.*; public class MacScreen extends Screen { + static { + MacDisplay.initSingleton(); + } + public MacScreen() { - MacWindow.initSingleton(); } protected void createNative(int index) { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(MacWindow.getScreenWidth(getIndex()), MacWindow.getScreenHeight(getIndex())); + setScreenSize(getWidthImpl(getIndex()), getHeightImpl(getIndex())); } protected void closeNative() { } + + private static native int getWidthImpl(int scrn_idx); + private static native int getHeightImpl(int scrn_idx); } diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java index 2c1ca7c89..704b578c4 100755 --- a/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java @@ -41,8 +41,6 @@ import com.sun.javafx.newt.impl.*; public class MacWindow extends Window { - private static native boolean initIDs(); - // Window styles private static final int NSBorderlessWindowMask = 0; private static final int NSTitledWindowMask = 1 << 0; @@ -129,31 +127,14 @@ public class MacWindow extends Window { private static final int NSHelpFunctionKey = 0xF746; private static final int NSModeSwitchFunctionKey = 0xF747; - // sync the MacOSX resources .. NSView, ie toggle fullscreen, window create - private Object nsViewLock = new Object(); - private volatile long surfaceHandle; // non fullscreen dimensions .. private int nfs_width, nfs_height, nfs_x, nfs_y; static { - initSingleton(); + MacDisplay.initSingleton(); } - private static volatile boolean isInit = false; - - public static synchronized void initSingleton() { - if(isInit) return; - isInit=true; - - NativeLibLoader.loadNEWT(); - - if(!initIDs()) { - throw new NativeWindowException("Failed to initialize jmethodIDs"); - } - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.initIDs OK "+Thread.currentThread().getName()); - } - public MacWindow() { } @@ -166,12 +147,15 @@ public class MacWindow extends Window { class CloseAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); if (windowHandle != 0) { close0(windowHandle); windowHandle = 0; } + } finally { + nsViewLock.unlock(); } } } @@ -182,20 +166,70 @@ public class MacWindow extends Window { } public long getWindowHandle() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { return windowHandle; + } finally { + nsViewLock.unlock(); } } public long getSurfaceHandle() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { return surfaceHandle; + } finally { + nsViewLock.unlock(); } } + private ToolkitLock nsViewLock = new ToolkitLock() { + private Thread owner; + private int recursionCount; + + public synchronized void lock() { + Thread cur = Thread.currentThread(); + if (owner == cur) { + ++recursionCount; + return; + } + while (owner != null) { + try { + wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + owner = cur; + } + + public synchronized void unlock() { + if (owner != Thread.currentThread()) { + throw new RuntimeException("Not owner"); + } + if (recursionCount > 0) { + --recursionCount; + return; + } + owner = null; + notifyAll(); + } + }; + + public synchronized int lockSurface() throws NativeWindowException { + nsViewLock.lock(); + return super.lockSurface(); + } + + public void unlockSurface() { + super.unlockSurface(); + nsViewLock.unlock(); + } + class VisibleAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); if (visible) { createWindow(false); @@ -204,6 +238,8 @@ public class MacWindow extends Window { orderOut(windowHandle); } } + } finally { + nsViewLock.unlock(); } } } @@ -216,10 +252,13 @@ public class MacWindow extends Window { class TitleAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if (windowHandle != 0) { setTitle0(windowHandle, title); } + } finally { + nsViewLock.unlock(); } } } @@ -232,10 +271,13 @@ public class MacWindow extends Window { class FocusAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if (windowHandle != 0) { makeKey(windowHandle); } + } finally { + nsViewLock.unlock(); } } } @@ -248,10 +290,13 @@ public class MacWindow extends Window { class SizeAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if (windowHandle != 0) { setContentSize(windowHandle, width, height); } + } finally { + nsViewLock.unlock(); } } } @@ -269,10 +314,13 @@ public class MacWindow extends Window { class PositionAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if (windowHandle != 0) { setFrameTopLeftPoint(windowHandle, x, y); } + } finally { + nsViewLock.unlock(); } } } @@ -288,26 +336,16 @@ public class MacWindow extends Window { MainThread.invoke(true, positionAction); } - class DispatchAction implements Runnable { - public void run() { - dispatchMessages0(windowHandle, eventMask); - } - } - private DispatchAction dispatchAction = new DispatchAction(); - private int eventMask; - - public void dispatchMessages(int eventMask) { - this.eventMask=eventMask; - MainThread.invoke(false, dispatchAction); - } - class FullscreenAction implements Runnable { public void run() { - synchronized(nsViewLock) { + nsViewLock.lock(); + try { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); } createWindow(true); + } finally { + nsViewLock.unlock(); } } } @@ -495,6 +533,7 @@ public class MacWindow extends Window { sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); } + protected static native boolean initIDs(); private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, @@ -504,11 +543,8 @@ public class MacWindow extends Window { private native void orderOut(long window); private native void close0(long window); private native void setTitle0(long window, String title); - protected native void dispatchMessages0(long window, int eventMask); private native long contentView(long window); private native long changeContentView(long window, long view); private native void setContentSize(long window, int w, int h); private native void setFrameTopLeftPoint(long window, int x, int y); - protected static native int getScreenWidth(int scrn_idx); - protected static native int getScreenHeight(int scrn_idx); } 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 5d50792db..8ecfe6216 100644 --- a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java @@ -37,6 +37,7 @@ import com.sun.javafx.newt.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.sun.opengl.impl.GLDrawableHelper; +import java.util.*; /** * An implementation of {@link Window} which is customized for OpenGL @@ -44,13 +45,20 @@ import com.sun.opengl.impl.GLDrawableHelper; * 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.). + * 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}. */ 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) */ @@ -68,7 +76,10 @@ public class GLWindow extends Window implements GLAutoDrawable { */ public static final int EVENT_HANDLER_GL_CURRENT = (1 << 0); + private static List/*GLWindow*/ glwindows = new ArrayList(); + private Window window; + private boolean runPumpMessages = true; /** Constructor. Do not call this directly -- use {@link create()} instead. */ @@ -94,6 +105,10 @@ public class GLWindow extends Window implements GLAutoDrawable { sendDestroy = true; } }); + + List newglw = (List) ((ArrayList) glwindows).clone(); + newglw.add(this); + glwindows=newglw; } /** Creates a new GLWindow on the local display, screen 0, with a @@ -132,10 +147,11 @@ public class GLWindow extends Window implements GLAutoDrawable { caps = new GLCapabilities(null); // default .. } + Display display; boolean ownerOfDisplayAndScreen=false; if (window == null) { ownerOfDisplayAndScreen = true; - Display display = NewtFactory.createDisplay(null); // local display + display = NewtFactory.createDisplay(null); // local display Screen screen = NewtFactory.createScreen(display, 0); // screen 0 window = NewtFactory.createWindow(screen, caps, undecorated); } @@ -143,6 +159,24 @@ public class GLWindow extends Window implements GLAutoDrawable { return new GLWindow(window, ownerOfDisplayAndScreen); } + /** + * EXPERIMENTAL<br> + * Enable or disables running the {@link Display#pumpMessages} in the {@link #display()} call.<br> + * The default behavior is to run {@link Display#pumpMessages}.<P> + * + * The idea was that in a single threaded environment with one {@link Display} and many {@link Window}'s, + * a performance benefit was expected while disabling the implicit {@link Display#pumpMessages} and + * do it once via {@link GLWindow#runCurrentThreadPumpMessage()} <br> + * This could not have been verified. No measurable difference could have been recognized.<P> + * + * Best performance has been achieved with one GLWindow per thread.<br> + * + * @deprecated EXPERIMENTAL, semantic is about to be removed after further verification. + */ + public void setRunPumpMessages(boolean onoff) { + runPumpMessages = onoff; + } + protected void createNative(Capabilities caps) { shouldNotCallThis(); } @@ -202,6 +236,10 @@ public class GLWindow extends Window implements GLAutoDrawable { e1.printStackTrace(); } + List newglw = (List) ((ArrayList) glwindows).clone(); + newglw.remove(this); + glwindows=newglw; + dispose(false); Screen _screen = null; @@ -251,57 +289,7 @@ public class GLWindow extends Window implements GLAutoDrawable { public int getEventHandlerMode() { return eventHandlerMode; } - - public void pumpMessages(int eventMask) { - if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) { - window.pumpMessages(eventMask); - } else { - pumpMessagesWithEventMaskAction.eventMask = eventMask; - pumpMessagesImpl(pumpMessagesWithEventMaskAction); - } - } - - public void pumpMessages() { - if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) { - window.pumpMessages(); - } else { - pumpMessagesImpl(pumpMessagesAction); - } - } - - class PumpMessagesWithEventMaskAction implements Runnable { - private int eventMask; - - public void run() { - window.pumpMessages(eventMask); - } - } - private PumpMessagesWithEventMaskAction pumpMessagesWithEventMaskAction = new PumpMessagesWithEventMaskAction(); - - class PumpMessagesAction implements Runnable { - public void run() { - window.pumpMessages(); - } - } - private PumpMessagesAction pumpMessagesAction = new PumpMessagesAction(); - - private void pumpMessagesImpl(Runnable pumpMessagesAction) { - // pumpMessagesAction.run(); - - boolean autoSwapBuffer = helper.getAutoSwapBufferMode(); - helper.setAutoSwapBufferMode(false); - try { - helper.invokeGL(drawable, context, pumpMessagesAction, initAction); - } finally { - helper.setAutoSwapBufferMode(autoSwapBuffer); - } - - } - - protected void dispatchMessages(int eventMask) { - shouldNotCallThis(); - } - + public void setVisible(boolean visible) { window.setVisible(visible); if (visible && context == null) { @@ -423,7 +411,8 @@ public class GLWindow extends Window implements GLAutoDrawable { // OpenGL-related methods and state // - private int eventHandlerMode = EVENT_HANDLER_GL_CURRENT; + private static int eventHandlerMode = EVENT_HANDLER_GL_CURRENT; + private static boolean autoSwapBufferMode = true; private GLDrawableFactory factory; private GLDrawable drawable; private GLContext context; @@ -466,9 +455,69 @@ 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() { if(getSurfaceHandle()!=0) { - pumpMessages(); + if(runPumpMessages) { + displayPumpMessage.run(window.getScreen().getDisplay()); + } if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { dispose(true); } @@ -487,12 +536,14 @@ public class GLWindow extends Window implements GLAutoDrawable { } } + /** This implementation uses a static value */ public void setAutoSwapBufferMode(boolean onOrOff) { - helper.setAutoSwapBufferMode(onOrOff); + autoSwapBufferMode = onOrOff; } + /** This implementation uses a static value */ public boolean getAutoSwapBufferMode() { - return helper.getAutoSwapBufferMode(); + return autoSwapBufferMode; } public void swapBuffers() { @@ -555,6 +606,7 @@ public class GLWindow extends Window implements GLAutoDrawable { } } } + private DisplayAction displayAction = new DisplayAction(); public long getStartTime() { return startTime; } public long getCurrentTime() { return curTime; } @@ -567,14 +619,11 @@ public class GLWindow extends Window implements GLAutoDrawable { private int totalFrames = 0, lastFrames = 0; private boolean ownerOfDisplayAndScreen; - private DisplayAction displayAction = new DisplayAction(); - class SwapBuffersAction implements Runnable { public void run() { drawable.swapBuffers(); } } - private SwapBuffersAction swapBuffersAction = new SwapBuffersAction(); //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java index a13a95586..64d640d11 100755 --- a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java @@ -40,10 +40,25 @@ import javax.media.nativewindow.*; import javax.media.nativewindow.egl.*; public class KDDisplay extends Display { + static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + NativeLibLoader.loadNEWT(); + + if (!KDWindow.initIDs()) { + throw new NativeWindowException("Failed to initialize KDWindow jmethodIDs"); + } } + public KDDisplay() { } @@ -64,5 +79,11 @@ public class KDDisplay extends Display { EGL.eglTerminate(aDevice.getHandle()); } } + + protected void dispatchMessages() { + DispatchMessages(); + } + + private native void DispatchMessages(); } diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java index 752a55752..1767c1240 100755 --- a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java @@ -37,6 +37,10 @@ import com.sun.javafx.newt.*; import javax.media.nativewindow.*; public class KDScreen extends Screen { + static { + KDDisplay.initSingleton(); + } + public KDScreen() { } diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java index 587bf185e..df0134c8e 100755 --- a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java @@ -47,11 +47,7 @@ public class KDWindow extends Window { private int nfs_width, nfs_height, nfs_x, nfs_y; static { - NativeLibLoader.loadNEWT(); - - if (!initIDs()) { - throw new NativeWindowException("Failed to initialize jmethodIDs"); - } + KDDisplay.initSingleton(); } public KDWindow() { @@ -67,8 +63,7 @@ public class KDWindow extends Window { int[] eglAttribs = EGLGraphicsConfiguration.GLCapabilities2AttribList(eglCaps, EGL.EGL_WINDOW_BIT); windowHandle = 0; - windowID = ++_windowID; - eglWindowHandle = CreateWindow(windowID, getDisplayHandle(), eglAttribs); + eglWindowHandle = CreateWindow(getDisplayHandle(), eglAttribs); if (eglWindowHandle == 0) { throw new NativeWindowException("Error creating egl window: "+config); } @@ -78,7 +73,8 @@ public class KDWindow extends Window { protected void closeNative() { if(0!=windowHandleClose) { - CloseWindow(windowHandleClose); + CloseWindow(windowHandleClose, windowUserData); + windowUserData=0; } } @@ -118,22 +114,21 @@ public class KDWindow extends Window { return true; } - protected void dispatchMessages(int eventMask) { - DispatchMessages(windowID, eglWindowHandle, eventMask); - } - //---------------------------------------------------------------------- // Internals only // - private static native boolean initIDs(); - private native long CreateWindow(int owner, long displayHandle, int[] attributes); + protected static native boolean initIDs(); + private native long CreateWindow(long displayHandle, int[] attributes); private native long RealizeWindow(long eglWindowHandle); - private native int CloseWindow(long eglWindowHandle); + private native int CloseWindow(long eglWindowHandle, long userData); private native void setVisible0(long eglWindowHandle, boolean visible); private native void setSize0(long eglWindowHandle, int width, int height); private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); - private native void DispatchMessages(int owner, long eglWindowHandle, int eventMask); + + private void windowCreated(long userData) { + windowUserData=userData; + } private void sizeChanged(int newWidth, int newHeight) { width = newWidth; @@ -149,6 +144,5 @@ public class KDWindow extends Window { private long eglWindowHandle; private long windowHandleClose; - private int windowID; - private static int _windowID = 0; + private long windowUserData; } diff --git a/src/newt/classes/com/sun/javafx/newt/util/MainThread.java b/src/newt/classes/com/sun/javafx/newt/util/MainThread.java index 01604476d..bb3718a83 100644 --- a/src/newt/classes/com/sun/javafx/newt/util/MainThread.java +++ b/src/newt/classes/com/sun/javafx/newt/util/MainThread.java @@ -44,7 +44,7 @@ import javax.media.nativewindow.*; import com.sun.javafx.newt.*; import com.sun.javafx.newt.impl.*; -import com.sun.javafx.newt.macosx.MacWindow; +import com.sun.javafx.newt.macosx.MacDisplay; import com.sun.nativewindow.impl.NWReflection; /** @@ -167,7 +167,7 @@ public class MainThread { mainAction = new MainAction(mainClassName, mainClassArgs); if(NativeWindowFactory.getNativeWindowType(false)==NativeWindowFactory.TYPE_MACOSX) { - MacWindow.initSingleton(); + MacDisplay.initSingleton(); } if ( USE_MAIN_THREAD ) { diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java index 436101a35..975281c95 100755 --- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java @@ -33,11 +33,35 @@ package com.sun.javafx.newt.windows; -import com.sun.javafx.newt.*; import javax.media.nativewindow.*; import javax.media.nativewindow.windows.*; +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; public class WindowsDisplay extends Display { + + protected static final String WINDOW_CLASS_NAME = "NewtWindowClass"; + private static int windowClassAtom; + private static long hInstance; + + static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + + NativeLibLoader.loadNEWT(); + + if (!WindowsWindow.initIDs()) { + throw new NativeWindowException("Failed to initialize WindowsWindow jmethodIDs"); + } + } + + public WindowsDisplay() { } @@ -45,5 +69,42 @@ public class WindowsDisplay extends Display { aDevice = new WindowsGraphicsDevice(); } - protected void closeNative() { } + protected void closeNative() { + // Can't do .. only at application shutdown + // UnregisterWindowClass(getWindowClassAtom(), getHInstance()); + } + + protected void dispatchMessages() { + DispatchMessages(); + } + + protected static synchronized int getWindowClassAtom() { + if(0 == windowClassAtom) { + windowClassAtom = RegisterWindowClass(WINDOW_CLASS_NAME, getHInstance()); + if (0 == windowClassAtom) { + throw new NativeWindowException("Error while registering window class"); + } + } + return windowClassAtom; + } + + protected static synchronized long getHInstance() { + if(0 == hInstance) { + hInstance = LoadLibraryW("newt"); + if (0 == hInstance) { + throw new NativeWindowException("Error finding HINSTANCE for \"newt\""); + } + } + return hInstance; + } + + //---------------------------------------------------------------------- + // Internals only + // + private static native long LoadLibraryW(String libraryName); + private static native int RegisterWindowClass(String windowClassName, long hInstance); + private static native void UnregisterWindowClass(int wndClassAtom, long hInstance); + + private static native void DispatchMessages(); } + diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java index 828cf4ca0..87ae1b49d 100755 --- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java @@ -39,19 +39,20 @@ import javax.media.nativewindow.*; public class WindowsScreen extends Screen { static { - NativeLibLoader.loadNEWT(); + WindowsDisplay.initSingleton(); } + public WindowsScreen() { } protected void createNative(int index) { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); - setScreenSize(getScreenWidth(getIndex()), getScreenHeight(getIndex())); + setScreenSize(getWidthImpl(getIndex()), getHeightImpl(getIndex())); } protected void closeNative() { } - private native int getScreenWidth(int scrn_idx); - private native int getScreenHeight(int scrn_idx); + private native int getWidthImpl(int scrn_idx); + private native int getHeightImpl(int scrn_idx); } 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 273be6653..c42aaa6d9 100755 --- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java @@ -47,11 +47,7 @@ public class WindowsWindow extends Window { private int nfs_width, nfs_height, nfs_x, nfs_y; static { - NativeLibLoader.loadNEWT(); - - if (!initIDs()) { - throw new NativeWindowException("Failed to initialize jmethodIDs"); - } + WindowsDisplay.initSingleton(); } public WindowsWindow() { @@ -96,11 +92,13 @@ public class WindowsWindow extends Window { } protected void createNative(Capabilities caps) { - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + WindowsScreen screen = (WindowsScreen) getScreen(); + WindowsDisplay display = (WindowsDisplay) screen.getDisplay(); + config = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, screen.getGraphicsScreen()); if (config == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } - windowHandle = CreateWindow(getWindowClassAtom(), WINDOW_CLASS_NAME, getHInstance(), 0, undecorated, x, y, width, height); + windowHandle = CreateWindow(display.getWindowClassAtom(), display.WINDOW_CLASS_NAME, display.getHInstance(), 0, undecorated, x, y, width, height); if (windowHandle == 0) { throw new NativeWindowException("Error creating window"); } @@ -121,7 +119,6 @@ public class WindowsWindow extends Window { } protected void windowDestroyed() { - // singleton ATOM CleanupWindowResources(getWindowClassAtom(), getHInstance()); windowHandleClose = 0; super.windowDestroyed(); } @@ -200,50 +197,19 @@ public class WindowsWindow extends Window { } } - protected void dispatchMessages(int eventMask) { - DispatchMessages(windowHandle, eventMask); - } - //---------------------------------------------------------------------- // Internals only // - private static final String WINDOW_CLASS_NAME = "NewtWindowClass"; - - private static int windowClassAtom = 0; - private static synchronized int getWindowClassAtom() { - if(0 == windowClassAtom) { - windowClassAtom = RegisterWindowClass(WINDOW_CLASS_NAME, getHInstance()); - if (windowClassAtom == 0) { - throw new NativeWindowException("Error while registering window class"); - } - } - return windowClassAtom; - } - private static long hInstance; - private static synchronized long getHInstance() { - if (hInstance == 0) { - hInstance = LoadLibraryW("newt"); - if (hInstance == 0) { - throw new NativeWindowException("Error finding HINSTANCE for \"newt\""); - } - } - return hInstance; - } - - private static native boolean initIDs(); - private static native long LoadLibraryW(String libraryName); - private static native int RegisterWindowClass(String windowClassName, long hInstance); + protected static native boolean initIDs(); private native long CreateWindow(int wndClassAtom, String wndName, long hInstance, long visualID, boolean isUndecorated, int x, int y, int width, int height); - private native void CleanupWindowResources(int wndClassAtom, long hInstance); private native void DestroyWindow(long windowHandle); private native long GetDC(long windowHandle); private native void ReleaseDC(long windowHandle, long hdc); private native long MonitorFromWindow(long windowHandle); private static native void setVisible0(long windowHandle, boolean visible); - private static native void DispatchMessages(long windowHandle, int eventMask); private native void setSize0(long windowHandle, int width, int height); private native void setPosition(long windowHandle, int x, int y); private native void setFullscreen0(long windowHandle, int x, int y, int width, int height, boolean isUndecorated, boolean on); 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 2371b20e8..99c0f599c 100755 --- a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java @@ -40,25 +40,65 @@ import javax.media.nativewindow.x11.*; public class X11Display extends Display { static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + NativeLibLoader.loadNEWT(); + + if (!initIDs()) { + throw new NativeWindowException("Failed to initialize X11Display jmethodIDs"); + } + + if (!X11Window.initIDs()) { + throw new NativeWindowException("Failed to initialize X11Window jmethodIDs"); + } } + public X11Display() { } protected void createNative() { - long handle = CreateDisplay(name); + long handle= CreateDisplay(name); if (handle == 0 ) { throw new RuntimeException("Error creating display: "+name); } aDevice = new X11GraphicsDevice(handle); } - protected void closeNative() { } + protected void closeNative() { + DestroyDisplay(getHandle()); + } + + protected void dispatchMessages() { + DispatchMessages(getHandle(), javaObjectAtom, windowDeleteAtom); + } + + protected long getJavaObjectAtom() { return javaObjectAtom; } + protected long getWindowDeleteAtom() { return windowDeleteAtom; } //---------------------------------------------------------------------- // Internals only // + private static native boolean initIDs(); private native long CreateDisplay(String name); + private native void DestroyDisplay(long handle); + + private native void DispatchMessages(long display, long javaObjectAtom, long windowDeleteAtom); + + private void displayCreated(long javaObjectAtom, long windowDeleteAtom) { + this.javaObjectAtom=javaObjectAtom; + this.windowDeleteAtom=windowDeleteAtom; + } + + private long windowDeleteAtom; + private long javaObjectAtom; } + diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java index 36d9d8baf..cee576e2c 100755 --- a/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java @@ -39,10 +39,12 @@ import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; public class X11Screen extends Screen { + static { - NativeLibLoader.loadNEWT(); + X11Display.initSingleton(); } + public X11Screen() { } 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 3badcce16..bd6bb42c2 100755 --- a/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java @@ -44,34 +44,34 @@ public class X11Window extends Window { private int nfs_width, nfs_height, nfs_x, nfs_y; static { - NativeLibLoader.loadNEWT(); - - if (!initIDs()) { - throw new NativeWindowException("Failed to initialize jmethodIDs"); - } + X11Display.initSingleton(); } public X11Window() { } protected void createNative(Capabilities caps) { - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + X11Screen screen = (X11Screen) getScreen(); + X11Display display = (X11Display) screen.getDisplay(); + config = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, screen.getGraphicsScreen()); if (config == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; long visualID = x11config.getVisualID(); - long w = CreateWindow(getDisplayHandle(), getScreenIndex(), visualID, x, y, width, height); + long w = CreateWindow(display.getHandle(), screen.getIndex(), visualID, + display.getJavaObjectAtom(), display.getWindowDeleteAtom(), x, y, width, height); if (w == 0 || w!=windowHandle) { throw new NativeWindowException("Error creating window: "+w); } windowHandleClose = windowHandle; - displayHandleClose = getDisplayHandle(); + displayHandleClose = display.getHandle(); } protected void closeNative() { if(0!=displayHandleClose && 0!=windowHandleClose) { - CloseWindow(displayHandleClose, windowHandleClose); + X11Display display = (X11Display) getScreen().getDisplay(); + CloseWindow(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); windowHandleClose = 0; displayHandleClose = 0; } @@ -91,6 +91,10 @@ public class X11Window extends Window { } } + public void requestFocus() { + super.requestFocus(); + } + public void setSize(int width, int height) { if(!fullscreen) { nfs_width=width; @@ -129,20 +133,15 @@ public class X11Window extends Window { return fullscreen; } - protected void dispatchMessages(int eventMask) { - DispatchMessages(getDisplayHandle(), windowHandle, eventMask, windowDeleteAtom); - } - //---------------------------------------------------------------------- // Internals only // - private static native boolean initIDs(); + protected static native boolean initIDs(); private native long CreateWindow(long display, int screen_index, - long visualID, int x, int y, int width, int height); - private native void CloseWindow(long display, long windowHandle); + long visualID, long javaObjectAtom, long windowDeleteAtom, int x, int y, int width, int height); + private native void CloseWindow(long display, long windowHandle, long javaObjectAtom); private native void setVisible0(long display, long windowHandle, boolean visible); - private native void DispatchMessages(long display, long windowHandle, int eventMask, long windowDeleteAtom); private native void setSize0(long display, int screen_index, long windowHandle, int x, int y, int width, int height, int decorationToggle, boolean isVisible); private native void setPosition0(long display, long windowHandle, int x, int y); @@ -167,12 +166,10 @@ public class X11Window extends Window { sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } - private void windowCreated(long windowHandle, long windowDeleteAtom) { + private void windowCreated(long windowHandle) { this.windowHandle = windowHandle; - this.windowDeleteAtom=windowDeleteAtom; } private long windowHandleClose; private long displayHandleClose; - private long windowDeleteAtom; } diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index d08d5411c..682edff24 100755 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -81,16 +81,121 @@ #endif #endif -/** - * Window - */ - +#define JOGL_KD_USERDATA_MAGIC 0xDEADBEEF +typedef struct { + long magic; + KDWindow * kdWindow; + jobject javaWindow; +} JOGLKDUserdata; + +static jmethodID windowCreatedID = NULL; static jmethodID sizeChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowDestroyedID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; +/** + * Display + */ + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDDisplay_DispatchMessages + (JNIEnv *env, jobject obj) +{ + const KDEvent * evt; + int numEvents = 0; + + // Periodically take a break + while( numEvents<100 && NULL!=(evt=kdWaitEvent(0)) ) { + KDWindow *kdWindow; + jobject javaWindow; + JOGLKDUserdata * userData = (JOGLKDUserdata *)(intptr_t)evt->userptr; + if(NULL == userData || userData->magic!=JOGL_KD_USERDATA_MAGIC) { + DBG_PRINT( "event unrelated: evt type: 0x%X\n", evt->type); + continue; + } + kdWindow = userData->kdWindow; + javaWindow = userData->javaWindow; + DBG_PRINT( "[DispatchMessages]: userData %p, evt type: 0x%X\n", userData, evt->type); + + numEvents++; + + // FIXME: support resize and window re-positioning events + + switch(evt->type) { + case KD_EVENT_WINDOW_FOCUS: + { + KDboolean hasFocus; + kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_FOCUS, &hasFocus); + DBG_PRINT( "event window focus : src: %p\n", userData); + } + break; + case KD_EVENT_WINDOW_CLOSE: + { + DBG_PRINT( "event window close : src: %p\n", userData); + (*env)->CallVoidMethod(env, javaWindow, windowDestroyNotifyID); + // Called by Window.java: DestroyWindow(wnd); + // (*env)->CallVoidMethod(env, javaWindow, windowDestroyedID); + } + break; + case KD_EVENT_WINDOWPROPERTY_CHANGE: + { + const KDEventWindowProperty* prop = &evt->data.windowproperty; + switch (prop->pname) { + case KD_WINDOWPROPERTY_SIZE: + { + KDint32 v[2]; + if(!kdGetWindowPropertyiv(kdWindow, KD_WINDOWPROPERTY_SIZE, v)) { + DBG_PRINT( "event window size change : src: %p %dx%d\n", userData, v[0], v[1]); + (*env)->CallVoidMethod(env, javaWindow, sizeChangedID, (jint) v[0], (jint) v[1]); + } else { + DBG_PRINT( "event window size change error: src: %p %dx%d\n", userData, v[0], v[1]); + } + } + break; + case KD_WINDOWPROPERTY_FOCUS: + DBG_PRINT( "event window focus: src: %p\n", userData); + break; + case KD_WINDOWPROPERTY_VISIBILITY: + { + KDboolean visible; + kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visible); + DBG_PRINT( "event window visibility: src: %p, v:%d\n", userData, visible); + } + break; + default: + break; + } + } + break; + case KD_EVENT_INPUT_POINTER: + { + const KDEventInputPointer* ptr = &(evt->data.inputpointer); + // button idx: evt->data.input.index + // pressed = ev->data.input.value.i + // time = ev->timestamp + if(KD_INPUT_POINTER_SELECT==ptr->index) { + DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, + (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED, + (jint) 0, + (jint) ptr->x, (jint) ptr->y, 1, 0); + } else { + DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + 0, + (jint) ptr->x, (jint) ptr->y, 0, 0); + } + } + break; + } + } +} + +/** + * Window + */ + JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_kd_KDWindow_initIDs (JNIEnv *env, jclass clazz) { @@ -100,12 +205,14 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_kd_KDWindow_initIDs _wfreopen(TEXT(STDERR_FILE),L"w",stderr); #endif #endif + windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - if (sizeChangedID == NULL || + if (windowCreatedID == NULL || + sizeChangedID == NULL || windowDestroyNotifyID == NULL || windowDestroyedID == NULL || sendMouseEventID == NULL || @@ -118,15 +225,13 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_kd_KDWindow_initIDs } JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CreateWindow - (JNIEnv *env, jobject obj, jint owner, jlong display, jintArray jAttrs) + (JNIEnv *env, jobject obj, jlong display, jintArray jAttrs) { jint * attrs = NULL; jsize attrsLen; EGLDisplay dpy = (EGLDisplay)(intptr_t)display; KDWindow *window = 0; - DBG_PRINT( "[CreateWindow]: owner %d\n", owner); - if(dpy==NULL) { fprintf(stderr, "[CreateWindow] invalid display connection..\n"); return 0; @@ -143,15 +248,21 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CreateWindow return 0; } - /* passing the KDWindow instance for the eventuserptr */ - window = kdCreateWindow(dpy, attrs, (void *)(intptr_t)owner); + JOGLKDUserdata * userData = kdMalloc(sizeof(JOGLKDUserdata)); + userData->magic = JOGL_KD_USERDATA_MAGIC; + window = kdCreateWindow(dpy, attrs, (void *)userData); (*env)->ReleaseIntArrayElements(env, jAttrs, attrs, 0); if(NULL==window) { + kdFree(userData); fprintf(stderr, "[CreateWindow] failed: 0x%X\n", kdGetError()); + } else { + userData->javaWindow = (*env)->NewGlobalRef(env, obj); + userData->kdWindow = window; + (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) (intptr_t) userData); + DBG_PRINT( "[CreateWindow] ok: %p, userdata %p\n", window, userData); } - DBG_PRINT( "[CreateWindow] ok: %p, owner %d\n", window, (void *)(intptr_t)owner); return (jlong) (intptr_t) window; } @@ -171,10 +282,13 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_RealizeWindow } JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CloseWindow - (JNIEnv *env, jobject obj, jlong window) + (JNIEnv *env, jobject obj, jlong window, jlong juserData) { KDWindow *w = (KDWindow*) (intptr_t) window; + JOGLKDUserdata * userData = (JOGLKDUserdata*) (intptr_t) juserData; int res = kdDestroyWindow(w); + (*env)->DeleteGlobalRef(env, userData->javaWindow); + kdFree(userData); DBG_PRINT( "[CloseWindow] res: %d\n", res); return res; @@ -194,120 +308,6 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setVisible0 DBG_PRINT( "[setVisible] v=%d\n", visible); } -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_DispatchMessages - (JNIEnv *env, jobject obj, jint owner, jlong window, jint eventMask) -{ - KDWindow *w = (KDWindow*) (intptr_t) window; - const KDEvent * evt; - - // Periodically take a break - while( NULL!=(evt=kdWaitEvent(0)) ) { - jint src_owner = (jint)(intptr_t)evt->userptr; - if(src_owner != owner) { - DBG_PRINT( "event unrelated: src: %d, caller: %d, evt type: 0x%X\n", src_owner, owner, evt->type); - continue; - } - DBG_PRINT( "[DispatchMessages]: caller %d, evt type: 0x%X\n", owner, evt->type); - - switch(evt->type) { - case KD_EVENT_INPUT_POINTER: - if( ! ( eventMask & EVENT_MOUSE ) ) { - DBG_PRINT( "event mouse ignored: src: %d\n", owner); - continue; - } - break; - /* - case KeyPress: - case KeyRelease: - if( ! ( eventMask & EVENT_KEY ) ) { - DBG_PRINT( "event key ignored: src: %d\n", owner); - continue; - } - break; - */ - case KD_EVENT_WINDOW_FOCUS: - case KD_EVENT_WINDOW_CLOSE: - case KD_EVENT_WINDOWPROPERTY_CHANGE: - case KD_EVENT_WINDOW_REDRAW: - if( ! ( eventMask & EVENT_WINDOW ) ) { - DBG_PRINT( "event window ignored: src: %d\n", owner); - continue; - } - break; - } - - // FIXME: support resize and window re-positioning events - - switch(evt->type) { - case KD_EVENT_WINDOW_FOCUS: - { - KDboolean hasFocus; - kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_FOCUS, &hasFocus); - DBG_PRINT( "event window focus : src: %d\n", owner); - } - break; - case KD_EVENT_WINDOW_CLOSE: - { - DBG_PRINT( "event window close : src: %d\n", owner); - (*env)->CallVoidMethod(env, obj, windowDestroyNotifyID); - // Called by Window.java: DestroyWindow(wnd); - // (*env)->CallVoidMethod(env, obj, windowDestroyedID); - } - break; - case KD_EVENT_WINDOWPROPERTY_CHANGE: - { - const KDEventWindowProperty* prop = &evt->data.windowproperty; - switch (prop->pname) { - case KD_WINDOWPROPERTY_SIZE: - { - KDint32 v[2]; - if(!kdGetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v)) { - DBG_PRINT( "event window size change : src: %d %dx%d\n", owner, v[0], v[1]); - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) v[0], (jint) v[1]); - } else { - DBG_PRINT( "event window size change error: src: %d %dx%d\n", owner, v[0], v[1]); - } - } - break; - case KD_WINDOWPROPERTY_FOCUS: - DBG_PRINT( "event window focus: src: %d\n", owner); - break; - case KD_WINDOWPROPERTY_VISIBILITY: - { - KDboolean visible; - kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &visible); - DBG_PRINT( "event window visibility: src: %d, v:%d\n", owner, visible); - } - break; - default: - break; - } - } - break; - case KD_EVENT_INPUT_POINTER: - { - const KDEventInputPointer* ptr = &(evt->data.inputpointer); - // button idx: evt->data.input.index - // pressed = ev->data.input.value.i - // time = ev->timestamp - if(KD_INPUT_POINTER_SELECT==ptr->index) { - DBG_PRINT( "event mouse click: src: %d, s:%d, (%d,%d)\n", owner, ptr->select, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, obj, sendMouseEventID, - (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED, - (jint) 0, - (jint) ptr->x, (jint) ptr->y, 1, 0); - } else { - DBG_PRINT( "event mouse: src: %d, s:%d, i:0x%X (%d,%d)\n", owner, ptr->select, ptr->index, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, - 0, - (jint) ptr->x, (jint) ptr->y, 0, 0); - } - } - break; - } - } -} - JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setFullScreen0 (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index f39a9f401..008a2417c 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -85,6 +85,7 @@ NS_ENDHANDLER if(NULL!=newView) { jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject); [newView setJavaWindowObject: globJavaWindowObject]; + [newView setJNIEnv: env]; } [win setContentView: newView]; @@ -92,11 +93,11 @@ NS_ENDHANDLER } /* - * Class: com_sun_javafx_newt_macosx_MacWindow + * Class: com_sun_javafx_newt_macosx_MacDisplay * Method: initIDs * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacDisplay_initNSApplication (JNIEnv *env, jclass clazz) { static int initialized = 0; @@ -122,6 +123,109 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs // printf("Going to sleep for 10 seconds\n"); // sleep(10); + return (jboolean) JNI_TRUE; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacDisplay + * Method: dispatchMessages0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacDisplay_dispatchMessages0 + (JNIEnv *env, jobject unused, jlong window, jint eventMask) +{ + NSEvent* event = NULL; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + +NS_DURING + + NSWindow* win = NULL; + NewtView* view = NULL; + int num_events = 0; + + // Periodically take a break + do { + // FIXME: ignoring event mask for the time being + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantPast] + inMode: NSDefaultRunLoopMode + dequeue: YES]; + if (event != NULL) { + [NSApp sendEvent: event]; + + num_events++; + } + } while (num_events<100 && event != NULL); + +NS_HANDLER + + // just ignore it .. + +NS_ENDHANDLER + + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacScreen + * Method: getWidthImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacScreen_getWidthImpl + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.width); +} + +/* + * Class: com_sun_javafx_newt_macosx_MacScreen + * Method: getHeightImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacScreen_getHeightImpl + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.height); +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + static int initialized = 0; + + if(initialized) return JNI_TRUE; + initialized = 1; + + // Need this when debugging, as it is necessary to attach gdb to + // the running java process -- "gdb java" doesn't work + // printf("Going to sleep for 10 seconds\n"); + // sleep(10); + return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; } @@ -280,51 +384,6 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setTitle0 /* * Class: com_sun_javafx_newt_macosx_MacWindow - * Method: dispatchMessages0 - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_dispatchMessages0 - (JNIEnv *env, jobject unused, jlong window, jint eventMask) -{ - NSEvent* event = NULL; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - -NS_DURING - - NSWindow* win = (NSWindow *) ((intptr_t) window); - - if(NULL != win) { - NewtView* view = (NewtView *) [win contentView]; - [view setJNIEnv: env]; - - do { - // FIXME: ignoring event mask for the time being - event = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: [NSDate distantPast] - inMode: NSDefaultRunLoopMode - dequeue: YES]; - if (event != NULL) { - win = (NSWindow*) [event window]; - view = (NewtView *) [win contentView]; - [view setJNIEnv: env]; - - [NSApp sendEvent: event]; - } - } while (event != NULL); - } - -NS_HANDLER - - // just ignore it .. - -NS_ENDHANDLER - - - [pool release]; -} - -/* - * Class: com_sun_javafx_newt_macosx_MacWindow * Method: contentView * Signature: (J)J */ @@ -386,45 +445,3 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setFrameTopLeft [pool release]; } -/* - * Class: com_sun_javafx_newt_macosx_MacWindow - * Method: getScreenWidth - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_getScreenWidth - (JNIEnv *env, jclass clazz, jint screen_idx) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; - NSRect rect = [screen frame]; - - [pool release]; - - return (jint) (rect.size.width); -} - -/* - * Class: com_sun_javafx_newt_macosx_MacWindow - * Method: getScreenHeight - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_getScreenHeight - (JNIEnv *env, jclass clazz, jint screen_idx) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; - NSRect rect = [screen frame]; - - [pool release]; - - return (jint) (rect.size.height); -} - diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 908eb2ac0..67fbd3f07 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -778,61 +778,34 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, } /* - * Class: com_sun_javafx_newt_windows_WindowsScreen - * Method: getScreenWidth - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getScreenWidth - (JNIEnv *env, jobject obj, jint scrn_idx) -{ - return (jint)GetSystemMetrics(SM_CXSCREEN); -} - -/* - * Class: com_sun_javafx_newt_windows_WindowsScreen - * Method: getScreenWidth - * Signature: (I)I - */ -JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getScreenHeight - (JNIEnv *env, jobject obj, jint scrn_idx) -{ - return (jint)GetSystemMetrics(SM_CYSCREEN); -} - -/* - * Class: com_sun_javafx_newt_windows_WindowsWindow - * Method: initIDs - * Signature: ()Z + * Class: com_sun_javafx_newt_windows_WindowsDisplay + * Method: DispatchMessages + * Signature: ()V */ -JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initIDs +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsDisplay_DispatchMessages (JNIEnv *env, jclass clazz) { - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - if (sizeChangedID == NULL || - positionChangedID == NULL || - focusChangedID == NULL || - windowDestroyNotifyID == NULL || - windowDestroyedID == NULL || - sendMouseEventID == NULL || - sendKeyEventID == NULL) { - return JNI_FALSE; - } - BuildDynamicKeyMapTable(); - return JNI_TRUE; + int i = 0; + MSG msg; + BOOL gotOne; + + // Periodically take a break + do { + gotOne = PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE); + if (gotOne) { + ++i; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } while (gotOne && i < 100); } /* - * Class: com_sun_javafx_newt_windows_WindowsWindow + * Class: com_sun_javafx_newt_windows_WindowsDisplay * Method: LoadLibraryW * Signature: (Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_LoadLibraryW +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsDisplay_LoadLibraryW (JNIEnv *env, jclass clazz, jstring dllName) { jchar* _dllName = GetNullTerminatedStringChars(env, dllName); @@ -842,11 +815,11 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_LoadLibra } /* - * Class: com_sun_javafx_newt_windows_WindowsWindow + * Class: com_sun_javafx_newt_windows_WindowsDisplay * Method: RegisterWindowClass * Signature: (Ljava/lang/String;J)I */ -JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_RegisterWindowClass +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsDisplay_RegisterWindowClass (JNIEnv *env, jclass clazz, jstring wndClassName, jlong hInstance) { ATOM res; @@ -882,17 +855,67 @@ JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_RegisterWi } /* - * Class: com_sun_javafx_newt_windows_WindowsWindow + * Class: com_sun_javafx_newt_windows_WindowsDisplay * Method: CleanupWindowResources * Signature: (java/lang/String;J)V */ -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CleanupWindowResources - (JNIEnv *env, jobject obj, jint wndClassAtom, jlong hInstance) +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsDisplay_UnregisterWindowClass + (JNIEnv *env, jclass clazz, jint wndClassAtom, jlong hInstance) { UnregisterClass(MAKEINTATOM(wndClassAtom), (HINSTANCE) hInstance); } /* + * Class: com_sun_javafx_newt_windows_WindowsScreen + * Method: getWidthImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getWidthImpl + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + return (jint)GetSystemMetrics(SM_CXSCREEN); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsScreen + * Method: getWidthImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getHeightImpl + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + return (jint)GetSystemMetrics(SM_CYSCREEN); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + positionChangedID == NULL || + focusChangedID == NULL || + windowDestroyNotifyID == NULL || + windowDestroyedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + return JNI_FALSE; + } + BuildDynamicKeyMapTable(); + return JNI_TRUE; +} + +/* * Class: com_sun_javafx_newt_windows_WindowsWindow * Method: CreateWindow * Signature: (ILjava/lang/String;JJZIIII)J @@ -1017,91 +1040,6 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setVisible /* * Class: com_sun_javafx_newt_windows_WindowsWindow - * Method: DispatchMessages - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_DispatchMessages - (JNIEnv *env, jclass clazz, jlong window, jint eventMask) -{ - int i = 0; - MSG msg; - BOOL gotOne; - WindowUserData * wud; - -#if defined(UNDER_CE) || _MSC_VER <= 1200 - wud = (WindowUserData *) GetWindowLong((HWND)window, GWL_USERDATA); -#else - wud = (WindowUserData *) GetWindowLongPtr((HWND)window, GWLP_USERDATA); -#endif - if(NULL==wud) { - fprintf(stderr, "INTERNAL ERROR in WindowsWindow::DispatchMessages window userdata NULL\n"); - exit(1); - } - - wud->jenv = env; - - if(eventMask<0) { - eventMask *= -1; - /* FIXME: re-select input mask - long xevent_mask_key = 0; - long xevent_mask_ptr = 0; - long xevent_mask_win = 0; - if( 0 != ( eventMask & EVENT_MOUSE ) ) { - xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; - } - if( 0 != ( eventMask & EVENT_KEY ) ) { - xevent_mask_key |= KeyPressMask|KeyReleaseMask; - } - if( 0 != ( eventMask & EVENT_WINDOW ) ) { - xevent_mask_win |= ExposureMask; - } - - XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); - */ - } - - // Periodically take a break - do { - gotOne = PeekMessage(&msg, (HWND) window, 0, 0, PM_REMOVE); - if (gotOne) { - ++i; - switch (msg.message) { - case WM_CLOSE: - case WM_DESTROY: - case WM_SIZE: - if( ! ( eventMask & EVENT_WINDOW ) ) { - continue; - } - break; - - case WM_CHAR: - case WM_KEYDOWN: - case WM_KEYUP: - if( ! ( eventMask & EVENT_KEY ) ) { - continue; - } - break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MOUSEMOVE: - if( ! ( eventMask & EVENT_MOUSE ) ) { - continue; - } - break; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } while (gotOne && i < 100); -} - -/* - * Class: com_sun_javafx_newt_windows_WindowsWindow * Method: setSize0 * Signature: (JII)V */ diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index c3d446f09..7ca3afe72 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -34,6 +34,8 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <stdarg.h> +#include <stdint.h> #include <unistd.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -48,7 +50,7 @@ // #define VERBOSE_ON 1 #ifdef VERBOSE_ON - #define DBG_PRINT(args...) fprintf(stderr, args) + #define DBG_PRINT(args...) fprintf(stderr, args); fflush(stderr); #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) @@ -121,12 +123,89 @@ static jint X11KeySym2NewtVKey(KeySym keySym) { return keySym; } +static const char * const ClazzNameRuntimeException = + "java/lang/RuntimeException"; +static jclass runtimeExceptionClz=NULL; + +static const char * const ClazzNameNewtWindow = + "com/sun/javafx/newt/Window"; +static jclass newtWindowClz=NULL; + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID windowCreatedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +static jmethodID displayCreatedID = NULL; + +static void _throwNewRuntimeException(JNIEnv *env, const char* msg, ...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, msg); + vsnprintf(buffer, sizeof(buffer), msg, ap); + va_end(ap); + + (*env)->ThrowNew(env, runtimeExceptionClz, buffer); +} + /** * Display */ /* * Class: com_sun_javafx_newt_x11_X11Display + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Display_initIDs + (JNIEnv *env, jclass clazz) +{ + jclass c; + + displayCreatedID = (*env)->GetMethodID(env, clazz, "displayCreated", "(JJ)V"); + if (displayCreatedID == NULL) { + return JNI_FALSE; + } + + if(NULL==newtWindowClz) { + c = (*env)->FindClass(env, ClazzNameNewtWindow); + if(NULL==c) { + fprintf(stderr, "FatalError: NEWT X11Window: can't find %s\n", ClazzNameNewtWindow); + return JNI_FALSE; + } + newtWindowClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==newtWindowClz) { + fprintf(stderr, "FatalError: NEWT X11Window: can't use %s\n", ClazzNameNewtWindow); + return JNI_FALSE; + } + } + + if(NULL==runtimeExceptionClz) { + c = (*env)->FindClass(env, ClazzNameRuntimeException); + if(NULL==c) { + fprintf(stderr, "FatalError: NEWT X11Window: can't find %s\n", ClazzNameRuntimeException); + return JNI_FALSE; + } + runtimeExceptionClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==runtimeExceptionClz) { + fprintf(stderr, "FatalError: NEWT X11Window: can't use %s\n", ClazzNameRuntimeException); + return JNI_FALSE; + } + } + + return JNI_TRUE; +} + + +/* + * Class: com_sun_javafx_newt_x11_X11Display * Method: CreateDisplay * Signature: (Ljava/lang/String;)J */ @@ -138,16 +217,229 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Display_CreateDisplay if(displayName!=0) { _displayName = (*env)->GetStringUTFChars(env, displayName, 0); } + DBG_PRINT("open display connection for %s ..\n", ((NULL==_displayName)?"NULL":_displayName)); dpy = XOpenDisplay(_displayName); + if(dpy==NULL) { + _throwNewRuntimeException(env, "couldn't open display connection for %s\n", ((NULL==_displayName)?"NULL":_displayName)); + } if(_displayName!=0) { (*env)->ReleaseStringChars(env, displayName, (const jchar *)_displayName); } - if(dpy==NULL) { - fprintf(stderr, "couldn't open display connection..\n"); + + jlong javaObjectAtom = (jlong) XInternAtom(dpy, "JOGL_JAVA_OBJECT", False); + if(None==javaObjectAtom) { + XCloseDisplay(dpy); + _throwNewRuntimeException(env, "could not create Atom JOGL_JAVA_OBJECT, bail out!\n"); + return 0; } + + jlong windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False); + if(None==windowDeleteAtom) { + XCloseDisplay(dpy); + _throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!\n"); + return 0; + } + + DBG_PRINT("X11Display_CreateDisplay dpy %p\n", dpy); + + (*env)->CallVoidMethod(env, obj, displayCreatedID, javaObjectAtom, windowDeleteAtom); + return (jlong) (intptr_t) dpy; } +/* + * Class: com_sun_javafx_newt_x11_X11Display + * Method: DestroyDisplay + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Display_DestroyDisplay + (JNIEnv *env, jobject obj, jlong display) +{ + Display * dpy = (Display *)(intptr_t)display; + DBG_PRINT("X11Display_DestroyDisplay dpy %p\n", dpy); + XCloseDisplay(dpy); +} + +static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { + int i=0; + dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ; + if(sizeof(uintptr_t) == 8) { + dst[i++] = (unsigned long) ( ( src >> 32 ) & 0xFFFFFFFF ) ; + } + return i; +} + +static uintptr_t getPtrOut32Long(unsigned long * src) { + uintptr_t res = ( (uintptr_t) ( src[0] & 0xFFFFFFFF ) ) << 0 ; + if(sizeof(uintptr_t) == 8) { + res |= ( (uintptr_t) ( src[1] & 0xFFFFFFFF ) ) << 32 ; + } + return res; +} + +static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, jobject jwindow) { + unsigned long jogl_java_object_data[2]; + int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) jwindow); + + { + 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); + } + } + + XChangeProperty( dpy, window, (Atom)javaObjectAtom, (Atom)javaObjectAtom, 32, PropModeReplace, + (unsigned char *)&jogl_java_object_data, nitems_32); +} + +static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom) { + Atom actual_type_return; + int actual_format_return; + int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; + unsigned char * jogl_java_object_data_pp = NULL; + jobject jwindow; + + { + unsigned long nitems_return = 0; + unsigned long bytes_after_return = 0; + jobject jwindow = NULL; + int res; + + res = XGetWindowProperty(dpy, window, (Atom)javaObjectAtom, 0, nitems_32, False, + (Atom)javaObjectAtom, &actual_type_return, &actual_format_return, + &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", + 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", + 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); + } +#endif + return jwindow; +} + +/* + * Class: com_sun_javafx_newt_x11_X11Display + * Method: DispatchMessages + * Signature: (JIJJ)V + */ +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; + + // Periodically take a break + while( num_events<100 && XPending(dpy)>0 ) { + jobject jwindow = NULL; + XEvent evt; + KeySym keySym; + char keyChar; + char text[255]; + + XNextEvent(dpy, &evt); + num_events++; + + if( 0==evt.xany.window ) { + _throwNewRuntimeException(env, "event window NULL, bail out!\n"); + } + + if(dpy!=evt.xany.display) { + _throwNewRuntimeException(env, "wrong display"); + continue; + } + jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom); + if(NULL==jwindow) { + // just leave .. _throwNewRuntimeException(env, "could not fetch Java Window object, bail out!\n"); + return; + } + + // FIXME: support resize and window re-positioning events + + switch(evt.type) { + case ButtonPress: + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + break; + case ButtonRelease: + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + break; + case MotionNotify: + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (jint) evt.xmotion.state, + (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); + break; + case FocusIn: + case FocusOut: + break; + case DestroyNotify: + DBG_PRINT( "event . DestroyNotify call 0x%X\n", evt.xdestroywindow.window); + (*env)->CallVoidMethod(env, jwindow, windowDestroyedID); + break; + case CreateNotify: + DBG_PRINT( "event . CreateNotify call 0x%X\n", evt.xcreatewindow.window); + (*env)->CallVoidMethod(env, jwindow, windowCreatedID); + break; + case VisibilityNotify: + DBG_PRINT( "event . VisibilityNotify call 0x%X\n", evt.xvisibility.window); + break; + case Expose: + DBG_PRINT( "event . Expose call 0x%X\n", evt.xexpose.window); + /* FIXME: Might want to send a repaint event .. */ + break; + case UnmapNotify: + DBG_PRINT( "event . UnmapNotify call 0x%X\n", evt.xunmap.window); + break; + case ClientMessage: + if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) { + DBG_PRINT( "event . ClientMessage call 0x%X type 0x%X !!!\n", evt.xclient.window, evt.xclient.message_type); + (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID); + // Called by Window.java: CloseWindow(); + } + break; + } + } +} + + /** * Screen */ @@ -195,14 +487,6 @@ JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_x11_X11Screen_getHeight0 * Window */ -static jmethodID sizeChangedID = NULL; -static jmethodID positionChangedID = NULL; -static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowDestroyedID = NULL; -static jmethodID windowCreatedID = NULL; -static jmethodID sendMouseEventID = NULL; -static jmethodID sendKeyEventID = NULL; - /* * Class: com_sun_javafx_newt_x11_X11Window * Method: initIDs @@ -215,9 +499,10 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Window_initIDs positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); - windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(JJ)V"); + windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || positionChangedID == NULL || windowDestroyNotifyID == NULL || @@ -237,7 +522,8 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Window_initIDs */ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow (JNIEnv *env, jobject obj, jlong display, jint screen_index, - jlong visualID, + jlong visualID, + jlong javaObjectAtom, jlong windowDeleteAtom, jint x, jint y, jint width, jint height) { Display * dpy = (Display *)(intptr_t)display; @@ -283,11 +569,11 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow XFree(pVisualQuery); pVisualQuery=NULL; } - DBG_PRINT( "trying given (screen %d, visualID: %d) found: %p\n", scrn_idx, (int)visualID, visual); + DBG_PRINT( "[CreateWindow] trying given (dpy %p, screen %d, visualID: %d) found: %p\n", dpy, scrn_idx, (int)visualID, visual); if (visual==NULL) { - fprintf(stderr, "could not query Visual by given VisualID, bail out!\n"); + _throwNewRuntimeException(env, "could not query Visual by given VisualID, bail out!\n"); return 0; } @@ -320,12 +606,31 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow visual, attrMask, &xswa); - Atom wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - XSetWMProtocols(dpy, window, &wm_delete_window, 1); + + Atom wm_delete_atom = (Atom)windowDeleteAtom; + XSetWMProtocols(dpy, window, &wm_delete_atom, 1); + + setJavaWindowProperty(env, dpy, window, javaObjectAtom, (*env)->NewGlobalRef(env, obj)); + XClearWindow(dpy, window); XSync(dpy, False); - (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) window, (jlong)wm_delete_window); + { + long xevent_mask = 0; + xevent_mask |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; + xevent_mask |= KeyPressMask|KeyReleaseMask; + xevent_mask |= ExposureMask | StructureNotifyMask | SubstructureNotifyMask | VisibilityNotify ; + XSelectInput(dpy, window, xevent_mask); + + /** + XGrabPointer(dpy, window, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, + GrabModeAsync, GrabModeAsync, window, None, CurrentTime); + XGrabKeyboard(dpy, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); + */ + } + + DBG_PRINT( "[CreateWindow] created window %p on display %p\n", window, dpy); + (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) window); return (jlong) window; } @@ -336,10 +641,21 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_CloseWindow - (JNIEnv *env, jobject obj, jlong display, jlong window) + (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom) { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; + jobject jwindow; + + jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom); + if(NULL==jwindow) { + _throwNewRuntimeException(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"); + } + (*env)->DeleteGlobalRef(env, jwindow); XSync(dpy, False); /** @@ -383,176 +699,6 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setVisible0 } } -/* - * Class: com_sun_javafx_newt_x11_X11Window - * Method: DispatchMessages - * Signature: (JJI)V - */ -JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_DispatchMessages - (JNIEnv *env, jobject obj, jlong display, jlong window, jint eventMask, jlong wmDeleteAtom) -{ - Display * dpy = (Display *) (intptr_t) display; - Window w = (Window)window; - Atom wm_delete_window = (Atom)wmDeleteAtom; - - if(eventMask<0) { - long xevent_mask_key = 0; - long xevent_mask_ptr = 0; - long xevent_mask_win = 0; - eventMask *= -1; - if( 0 != ( eventMask & EVENT_MOUSE ) ) { - xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; - } - if( 0 != ( eventMask & EVENT_KEY ) ) { - xevent_mask_key |= KeyPressMask|KeyReleaseMask; - } - if( 0 != ( eventMask & EVENT_WINDOW ) ) { - xevent_mask_win |= ExposureMask | StructureNotifyMask | SubstructureNotifyMask | VisibilityNotify ; - } - - XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); - - /** - if(0!=xevent_mask_ptr) { - XGrabPointer(dpy, w, True, xevent_mask_ptr, - GrabModeAsync, GrabModeAsync, w, None, CurrentTime); - } - if(0!=xevent_mask_key) { - XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); - } */ - - } - - // Periodically take a break - while( XPending(dpy)>0 ) { - XEvent evt; - KeySym keySym; - char keyChar; - char text[255]; - - XNextEvent(dpy, &evt); - - switch(evt.type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - if( ! ( eventMask & EVENT_MOUSE ) ) { - continue; - } - break; - case KeyPress: - case KeyRelease: - if( ! ( eventMask & EVENT_KEY ) ) { - continue; - } - break; - case FocusIn: - case FocusOut: - break; - case DestroyNotify: - case CreateNotify: - case VisibilityNotify: - case Expose: - case UnmapNotify: - if( ! ( eventMask & EVENT_WINDOW ) ) { - continue; - } - break; - } - - // FIXME: support resize and window re-positioning events - - switch(evt.type) { - case ButtonPress: - if(evt.xbutton.window==w) { - (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, - (jint) evt.xbutton.state, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - } - break; - case ButtonRelease: - if(evt.xbutton.window==w) { - (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, - (jint) evt.xbutton.state, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - } - break; - case MotionNotify: - if(evt.xmotion.window==w) { - (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, - (jint) evt.xmotion.state, - (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); - } - break; - case KeyPress: - if(evt.xkey.window==w) { - if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { - keyChar=text[0]; - } else { - keyChar=0; - } - (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_PRESSED, - (jint) evt.xkey.state, - X11KeySym2NewtVKey(keySym), (jchar) keyChar); - } - break; - case KeyRelease: - if(evt.xkey.window==w) { - if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { - keyChar=text[0]; - } else { - keyChar=0; - } - (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_RELEASED, - (jint) evt.xkey.state, - X11KeySym2NewtVKey(keySym), (jchar) keyChar); - } - break; - case FocusIn: - case FocusOut: - if(evt.xfocus.window==w) { - } - break; - case DestroyNotify: - if(evt.xdestroywindow.window==w) { - DBG_PRINT( "event . DestroyNotify call 0x%X\n", evt.xdestroywindow.window); - (*env)->CallVoidMethod(env, obj, windowDestroyedID); - } - break; - case CreateNotify: - if(evt.xcreatewindow.window==w) { - DBG_PRINT( "event . DestroyNotify call 0x%X\n", evt.xcreatewindow.window); - (*env)->CallVoidMethod(env, obj, windowCreatedID); - } - break; - case VisibilityNotify: - if(evt.xvisibility.window==w) { - DBG_PRINT( "event . VisibilityNotify call 0x%X\n", evt.xvisibility.window); - } - break; - case Expose: - if(evt.xexpose.window==w) { - DBG_PRINT( "event . Expose call 0x%X\n", evt.xexpose.window); - /* FIXME: Might want to send a repaint event .. */ - } - break; - case UnmapNotify: - if(evt.xunmap.window==w) { - DBG_PRINT( "event . UnmapNotify call 0x%X\n", evt.xunmap.window); - } - break; - case ClientMessage: - if (evt.xclient.window==w && evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_window) { - DBG_PRINT( "event . ClientMessage call 0x%X type 0x%X !!!\n", evt.xclient.window, evt.xclient.message_type); - (*env)->CallVoidMethod(env, obj, windowDestroyNotifyID); - // Called by Window.java: CloseWindow(); - } - break; - - } - } -} - #define MWM_FULLSCREEN 1 #ifdef MWM_FULLSCREEN @@ -612,7 +758,13 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setSize0 XSync(dpy, False); /** if(isVisible==JNI_TRUE) { + // this .. XSetInputFocus(dpy, w, RevertToNone, CurrentTime); + + // or this .. + unsigned long wmleader[1] = { (unsigned long) w}; + Atom prop = XInternAtom( dpy, "WM_CLIENT_LEADER", False ); + XChangeProperty( dpy, w, prop, prop, 32, PropModeReplace, (unsigned char *)&wmleader, 1); } */ DBG_PRINT( "setSize0 . sizeChangedID call\n"); |