diff options
Diffstat (limited to 'src/newt')
61 files changed, 3617 insertions, 2120 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 6a0ebe14a..7b6849a30 100644 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -30,7 +30,6 @@ package com.jogamp.newt; import com.jogamp.newt.util.EDTUtil; import jogamp.newt.Debug; -import jogamp.newt.DisplayImpl; import java.util.*; @@ -130,7 +129,10 @@ public abstract class Display { public abstract int getId(); /** - * @return this display instance name as defined at creation time + * @return This display connection name as defined at creation time. + * The display connection name is a technical platform specific detail, see {@link AbstractGraphicsDevice#getConnection()}. + * + * @see AbstractGraphicsDevice#getConnection() */ public abstract String getName(); @@ -198,6 +200,7 @@ public abstract class Display { } /** Returns the global display collection */ + @SuppressWarnings("unchecked") public static Collection<Display> getAllDisplays() { ArrayList<Display> list; synchronized(displayList) { diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index d3be098c0..4e6fa1aa5 100644 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -34,14 +34,19 @@ package com.jogamp.newt; -import javax.media.nativewindow.*; - -import com.jogamp.common.os.Platform; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowFactory; +import jogamp.newt.Debug; import jogamp.newt.DisplayImpl; import jogamp.newt.ScreenImpl; import jogamp.newt.WindowImpl; -import jogamp.newt.Debug; + +import com.jogamp.common.os.Platform; public class NewtFactory { public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); @@ -49,7 +54,6 @@ public class NewtFactory { // Work-around for initialization order problems on Mac OS X // between native Newt and (apparently) Fmod static { - Platform.initSingleton(); NativeWindowFactory.initSingleton(false); // last resort .. WindowImpl.init(NativeWindowFactory.getNativeWindowType(true)); } @@ -80,53 +84,124 @@ public class NewtFactory { public static boolean useEDT() { return useEDT; } /** - * Create a Display entity, incl native creation + * Create a Display entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Display#addReference()}. + * </p> + * <p> + * An already existing display connection of the same <code>name</code> will be reused. + * </p> + * @param name the display connection name which is a technical platform specific detail, + * see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default. + * @return the new or reused Display instance */ public static Display createDisplay(String name) { return createDisplay(name, true); } + /** + * Create a Display entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Display#addReference()}. + * </p> + * <p> + * An already existing display connection of the same <code>name</code> will be reused + * <b>if</b> <code>reuse</code> is <code>true</code>, otherwise a new instance is being created. + * </p> + * @param name the display connection name which is a technical platform specific detail, + * see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default. + * @param reuse attempt to reuse an existing Display with same <code>name</code> if set true, otherwise create a new instance. + * @return the new or reused Display instance + */ public static Display createDisplay(String name, boolean reuse) { return DisplayImpl.create(NativeWindowFactory.getNativeWindowType(true), name, 0, reuse); } /** - * Create a Display entity using the given implementation type, incl native creation + * Create a Display entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Display#addReference()}. + * </p> + * <p> + * An already existing display connection of the same <code>name</code> will be reused. + * </p> + * @param type explicit NativeWindow type eg. {@link NativeWindowFactory#TYPE_AWT} + * @param name the display connection name which is a technical platform specific detail, + * see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default. + * @return the new or reused Display instance */ public static Display createDisplay(String type, String name) { return createDisplay(type, name, true); } + /** + * Create a Display entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Display#addReference()}. + * </p> + * <p> + * An already existing display connection of the same <code>name</code> will be reused + * <b>if</b> <code>reuse</code> is <code>true</code>, otherwise a new instance is being created. + * </p> + * @param type explicit NativeWindow type eg. {@link NativeWindowFactory#TYPE_AWT} + * @param name the display connection name which is a technical platform specific detail, + * see {@link AbstractGraphicsDevice#getConnection()}. Use <code>null</code> for default. + * @param reuse attempt to reuse an existing Display with same <code>name</code> if set true, otherwise create a new instance. + * @return the new or reused Display instance + */ public static Display createDisplay(String type, String name, boolean reuse) { return DisplayImpl.create(type, name, 0, reuse); } /** - * Create a Screen entity, incl native creation + * Create a Screen entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Screen#addReference()}. + * </p> + * <p> + * The lifecycle of this Screen's Display is handled via {@link Display#addReference()} + * and {@link Display#removeReference()}. + * </p> */ public static Screen createScreen(Display display, int index) { return ScreenImpl.create(display, index); } /** - * Create a top level Window entity, incl native creation.<br> - * The Display/Screen is created and owned, ie destructed atomatically.<br> - * A new Display is only created if no preexisting one could be found via {@link Display#getLastDisplayOf(java.lang.String, java.lang.String, int)}. + * Create a top level Window entity on the default Display and default Screen. + * <p> + * Native creation is lazily done at usage, ie. {@link Window#setVisible(boolean)}. + * </p> + * <p> + * An already existing default Display will be reused. + * </p> + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> */ public static Window createWindow(CapabilitiesImmutable caps) { return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), caps); } /** - * Create a top level Window entity, incl native creation + * Create a top level Window entity. + * <p> + * Native creation is lazily done at usage, ie. {@link Window#setVisible(boolean)}. + * </p> + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> */ public static Window createWindow(Screen screen, CapabilitiesImmutable caps) { return createWindowImpl(screen, caps); } /** - * Create a child Window entity attached to the given parent, incl native creation.<br> - * The Screen and Display information is regenerated utilizing the parents information.<br> + * Create a child Window entity attached to the given parent.<br> + * The Screen and Display information is regenerated utilizing the parents information, + * while reusing an existing Display.<br> * <p> * In case <code>parentWindowObject</code> is a {@link com.jogamp.newt.Window} instance,<br> * the new window is added to it's list of children.<br> @@ -138,38 +213,41 @@ public class NewtFactory { * In case <code>parentWindowObject</code> is a different {@link javax.media.nativewindow.NativeWindow} implementation,<br> * you have to handle all events appropriate.<br></p> * <p> + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> * * @param parentWindowObject either a NativeWindow instance */ - public static Window createWindow(NativeWindow nParentWindow, CapabilitiesImmutable caps) { + public static Window createWindow(NativeWindow parentWindow, CapabilitiesImmutable caps) { final String type = NativeWindowFactory.getNativeWindowType(true); - Screen screen = null; - Window parentWindow = null; + Window newtParentWindow = null; - if ( nParentWindow instanceof Window ) { + if ( parentWindow instanceof Window ) { // use parent NEWT Windows Display/Screen - parentWindow = (Window) nParentWindow ; - screen = parentWindow.getScreen(); + newtParentWindow = (Window) parentWindow ; + screen = newtParentWindow.getScreen(); } else { // create a Display/Screen compatible to the NativeWindow - AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); - if(null!=nParentConfig) { - AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); - AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - Display display = NewtFactory.createDisplay(type, nParentDevice.getHandle(), true); - screen = NewtFactory.createScreen(display, nParentScreen.getIndex()); + AbstractGraphicsConfiguration parentConfig = parentWindow.getGraphicsConfiguration(); + if(null!=parentConfig) { + AbstractGraphicsScreen parentScreen = parentConfig.getScreen(); + AbstractGraphicsDevice parentDevice = parentScreen.getDevice(); + Display display = NewtFactory.createDisplay(type, parentDevice.getHandle(), true); + screen = NewtFactory.createScreen(display, parentScreen.getIndex()); } else { Display display = NewtFactory.createDisplay(type, null, true); // local display screen = NewtFactory.createScreen(display, 0); // screen 0 } } - final Window win = createWindowImpl(nParentWindow, screen, caps); + final Window win = createWindowImpl(parentWindow, screen, caps); - win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); - if ( null != parentWindow ) { - parentWindow.addChild(win); - win.setVisible(parentWindow.isVisible()); + win.setSize(parentWindow.getWidth(), parentWindow.getHeight()); + if ( null != newtParentWindow ) { + newtParentWindow.addChild(win); + win.setVisible(newtParentWindow.isVisible()); } return win; } diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index d25d3e7ac..26f19ad6b 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -120,12 +120,22 @@ public abstract class Screen { public abstract int getIndex(); /** - * @return the current screen width + * @return the x position of the virtual top-left origin. + */ + public abstract int getX(); + + /** + * @return the y position of the virtual top-left origin. + */ + public abstract int getY(); + + /** + * @return the <b>rotated</b> virtual width. */ public abstract int getWidth(); /** - * @return the current screen height + * @return the <b>rotated</b> virtual height. */ public abstract int getHeight(); diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index a78f81668..32024a49a 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -30,12 +30,13 @@ package com.jogamp.newt; import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.MouseListener; import jogamp.newt.Debug; import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; -import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.nativewindow.WindowClosingProtocol; /** @@ -133,6 +134,11 @@ public interface Window extends NativeWindow, WindowClosingProtocol { boolean isVisible(); + /** + * If the implementation uses delegation, return the delegated {@link Window} instance, + * otherwise return <code>this</code> instance. */ + Window getDelegatedWindow(); + // // Child Window Management // @@ -310,16 +316,46 @@ public interface Window extends NativeWindow, WindowClosingProtocol { } /** - * May set to a {@link FocusRunnable}, {@link FocusRunnable#run()} before Newt requests the native focus. + * Sets a {@link FocusRunnable}, + * which {@link FocusRunnable#run()} method is executed before the native focus is requested. + * <p> * This allows notifying a covered window toolkit like AWT that the focus is requested, * hence focus traversal can be made transparent. + * </p> */ void setFocusAction(FocusRunnable focusAction); + + /** + * Sets a {@link KeyListener} allowing focus traversal with a covered window toolkit like AWT. + * <p> + * The {@link KeyListener} methods are invoked prior to all other {@link KeyListener}'s + * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}. + * </p> + * @param l + */ + void setKeyboardFocusHandler(KeyListener l); + /** + * Request focus for this native window + * <p> + * The request is handled on this Window EDT and blocked until finished. + * </p> + * + * @see #requestFocus(boolean) + */ void requestFocus(); - boolean hasFocus(); - + /** + * Request focus for this native window + * <p> + * The request is handled on this Window EDT. + * </p> + * + * @param wait true if waiting until the request is executed, otherwise false + * @see #requestFocus() + */ + void requestFocus(boolean wait); + void windowRepaint(int x, int y, int width, int height); void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event); @@ -328,38 +364,6 @@ public interface Window extends NativeWindow, WindowClosingProtocol { // - // SurfaceUpdateListener - // - - /** - * Appends the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} to the end of - * the list. - */ - void addSurfaceUpdatedListener(SurfaceUpdatedListener l); - - /** - * - * Inserts the given {@link com.jogamp.newt.event.SurfaceUpdatedListener} at the - * specified position in the list.<br> - * - * @param index Position where the listener will be inserted. - * Should be within (0 <= index && index <= size()). - * An index value of -1 is interpreted as the end of the list, size(). - * @param l The listener object to be inserted - * @throws IndexOutOfBoundsException If the index is not within (0 <= index && index <= size()), or -1 - */ - void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException; - - void removeAllSurfaceUpdatedListener(); - - void removeSurfaceUpdatedListener(SurfaceUpdatedListener l); - - SurfaceUpdatedListener getSurfaceUpdatedListener(int index); - - SurfaceUpdatedListener[] getSurfaceUpdatedListeners(); - - - // // WindowListener // diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 31d42d21b..a71c6106d 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -29,42 +29,56 @@ package com.jogamp.newt.awt; -import com.jogamp.newt.Display; -import java.lang.reflect.*; -import java.security.*; - +import java.awt.AWTKeyStroke; import java.awt.Canvas; -import java.awt.EventQueue; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Set; import javax.media.nativewindow.NativeWindow; -import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.OffscreenLayerOption; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.awt.AWTWindowClosingProtocol; +import javax.swing.MenuSelectionManager; + import jogamp.nativewindow.awt.AWTMisc; +import jogamp.nativewindow.jawt.JAWTWindow; +import jogamp.newt.Debug; +import jogamp.newt.awt.NewtFactoryAWT; +import jogamp.newt.awt.event.AWTParentWindowAdapter; +import jogamp.newt.driver.DriverClearFocus; -import com.jogamp.newt.event.awt.AWTAdapter; -import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.Display; import com.jogamp.newt.Window; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.event.WindowListener; -import jogamp.newt.Debug; -import jogamp.newt.awt.event.AWTParentWindowAdapter; -import jogamp.newt.awt.event.NewtFactoryAWT; - -import javax.swing.MenuSelectionManager; +import com.jogamp.newt.event.awt.AWTAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTMouseAdapter; @SuppressWarnings("serial") -public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol { +public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption { public static final boolean DEBUG = Debug.debug("Window"); - NativeWindow nativeWindow = null; - Window newtChild = null; - int newtChildCloseOp; - AWTAdapter awtAdapter = null; - + private JAWTWindow jawtWindow = null; + private boolean shallUseOffscreenLayer = false; + private Window newtChild = null; + private boolean isOnscreen = true; + private int newtChildCloseOp; + private AWTAdapter awtAdapter = null; + private AWTAdapter awtMouseAdapter = null; + private AWTAdapter awtKeyAdapter = null; + private AWTWindowClosingProtocol awtWindowClosingProtocol = new AWTWindowClosingProtocol(this, new Runnable() { public void run() { @@ -102,53 +116,136 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto setNEWTChild(child); } + public void setShallUseOffscreenLayer(boolean v) { + shallUseOffscreenLayer = v; + } + + public final boolean getShallUseOffscreenLayer() { + return shallUseOffscreenLayer; + } + + public final boolean isOffscreenLayerSurfaceEnabled() { + return jawtWindow.isOffscreenLayerSurfaceEnabled(); + } + + /** + * Returns true if the AWT component is parented to an {@link java.applet.Applet}, + * otherwise false. This information is valid only after {@link #addNotify()} is issued, + * ie. before adding the component to the AWT tree and make it visible. + */ + public boolean isApplet() { + return jawtWindow.isApplet(); + } + class FocusAction implements Window.FocusRunnable { public boolean run() { - if ( EventQueue.isDispatchThread() ) { - focusActionImpl.run(); - } else { - try { - EventQueue.invokeAndWait(focusActionImpl); - } catch (Exception e) { - throw new NativeWindowException(e); - } - /** - // wait for AWT focus ! - for(long sleep = Window.TIMEOUT_NATIVEWINDOW; 0<sleep && !isFocusOwner(); sleep-=10 ) { - try { Thread.sleep(10); } catch (InterruptedException e) { } - } */ + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()); } - return focusActionImpl.result; - } - - class FocusActionImpl implements Runnable { - public final boolean result = false; // NEWT shall always proceed requesting the native focus - public void run() { - if(DEBUG) { - System.err.println("FocusActionImpl.run() "+Display.getThreadName()); - } - NewtCanvasAWT.this.requestFocusAWTParent(); + // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. + if(!hasFocus()) { + // Acquire the AWT focus 1st for proper AWT traversal + NewtCanvasAWT.super.requestFocus(); + } + if(isOnscreen) { + // Remove the AWT focus in favor of the native NEWT focus KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); } + return false; // NEWT shall proceed requesting the native focus } - FocusActionImpl focusActionImpl = new FocusActionImpl(); } - FocusAction focusAction = new FocusAction(); + private FocusAction focusAction = new FocusAction(); WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() { @Override public void windowGainedFocus(WindowEvent arg0) { - MenuSelectionManager.defaultManager().clearSelectedPath(); + MenuSelectionManager.defaultManager().clearSelectedPath(); } }; - /** sets a new NEWT child, provoking reparenting on the NEWT level. */ - /*package */ NewtCanvasAWT setNEWTChild(Window child) { + class FocusTraversalKeyListener implements KeyListener { + boolean suppress = false; + + public void keyPressed(KeyEvent e) { + handleKey(e, false); + } + public void keyReleased(KeyEvent e) { + handleKey(e, true); + } + public void keyTyped(KeyEvent e) { + if(suppress) { + e.setAttachment(InputEvent.consumedTag); + suppress = false; // reset + } + } + + void handleKey(KeyEvent evt, boolean onRelease) { + if(null == keyboardFocusManager) { + throw new InternalError("XXX"); + } + final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease); + if(null != ks) { + final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); + final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); + if(fwdKeys.contains(ks)) { + if(DEBUG) { + System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()); + } + // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. + NewtCanvasAWT.this.transferFocus(); + suppress = true; + } else if(bwdKeys.contains(ks)) { + if(DEBUG) { + System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()); + } + // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. + NewtCanvasAWT.this.transferFocusBackward(); + suppress = true; + } + } + if(suppress) { + evt.setAttachment(InputEvent.consumedTag); + } + if(DEBUG) { + System.err.println("NewtCanvasAWT.focusKey: XXX: "+ks); + } + } + } + private final FocusTraversalKeyListener newtFocusTraversalKeyListener = new FocusTraversalKeyListener(); + + class FocusPropertyChangeListener implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent evt) { + final Object oldF = evt.getOldValue(); + final Object newF = evt.getNewValue(); + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF); + } + if(oldF == NewtCanvasAWT.this && newF == null) { + // focus traversal to NEWT - NOP + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus traversal"); + } + } else if(null != newF && newF != NewtCanvasAWT.this) { + // focus traversal to another AWT component + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus"); + } + if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) { + ((DriverClearFocus)newtChild.getDelegatedWindow()).clearFocus(); + } + } + } + } + private final FocusPropertyChangeListener focusPropertyChangeListener = new FocusPropertyChangeListener(); + private volatile KeyboardFocusManager keyboardFocusManager = null; + + /** sets a new NEWT child, provoking reparenting. */ + private NewtCanvasAWT setNEWTChild(Window child) { if(newtChild!=child) { newtChild = child; - if(null!=nativeWindow) { - java.awt.Container cont = AWTMisc.getContainer(this); + if(isDisplayable()) { // reparent right away, addNotify has been called already + final java.awt.Container cont = AWTMisc.getContainer(this); reparentWindow( (null!=child) ? true : false, cont ); } } @@ -162,8 +259,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto /** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called, * or {@link #addNotify()} hasn't been called yet.*/ - public NativeWindow getNativeWindow() { return nativeWindow; } - + public NativeWindow getNativeWindow() { return jawtWindow; } + public int getDefaultCloseOperation() { return awtWindowClosingProtocol.getDefaultCloseOperation(); } @@ -177,13 +274,41 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto awtAdapter.removeFrom(this); awtAdapter=null; } + if(null!=awtMouseAdapter) { + awtMouseAdapter.removeFrom(this); + awtMouseAdapter = null; + } + if(null!=awtKeyAdapter) { + awtKeyAdapter.removeFrom(this); + awtKeyAdapter = null; + } + newtChild.setKeyboardFocusHandler(null); + if(null != keyboardFocusManager) { + keyboardFocusManager.removePropertyChangeListener("focusOwner", focusPropertyChangeListener); + keyboardFocusManager = null; + } + if( null != newtChild ) { if(attach) { + if(null == jawtWindow.getGraphicsConfiguration()) { + throw new InternalError("XXX"); + } + isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); newtChild.addWindowListener(clearAWTMenusOnNewtFocus); newtChild.setFocusAction(focusAction); // enable AWT focus traversal newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingProtocol.DO_NOTHING_ON_CLOSE); awtWindowClosingProtocol.addClosingListenerOneShot(); + keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener); + if(isOnscreen) { + // onscreen newt child needs to fwd AWT focus + newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener); + } else { + // offscreen newt child requires AWT to fwd AWT key/mouse event + awtMouseAdapter = new AWTMouseAdapter(newtChild).addTo(this); + awtKeyAdapter = new AWTKeyAdapter(newtChild).addTo(this); + } } else { newtChild.removeWindowListener(clearAWTMenusOnNewtFocus); newtChild.setFocusAction(null); @@ -232,26 +357,47 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto newtChild.setFocusAction(null); // no AWT focus traversal .. if(add) { - nativeWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); - if(null!=nativeWindow) { - if(DEBUG) { - System.err.println("NewtCanvasAWT.reparentWindow: "+newtChild); - } - final int w = cont.getWidth(); - final int h = cont.getHeight(); - setSize(w, h); - newtChild.setSize(w, h); - newtChild.reparentWindow(nativeWindow); - newtChild.setVisible(true); - configureNewtChild(true); - newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener - newtChild.windowRepaint(0, 0, w, h); + jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); + jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); + if(DEBUG) { + System.err.println("NewtCanvasAWT.reparentWindow: newtChild: "+newtChild); + } + final int w; + final int h; + if(isPreferredSizeSet()) { + java.awt.Dimension d = getPreferredSize(); + w = d.width; + h = d.height; + } else { + final java.awt.Dimension min; + if(this.isMinimumSizeSet()) { + min = getMinimumSize(); + } else { + min = new java.awt.Dimension(0, 0); + } + java.awt.Insets ins = cont.getInsets(); + w = Math.max(min.width, cont.getWidth() - ins.left - ins.right); + h = Math.max(min.height, cont.getHeight() - ins.top - ins.bottom); } + setSize(w, h); + newtChild.setSize(w, h); + newtChild.reparentWindow(jawtWindow); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + newtChild.windowRepaint(0, 0, w, h); + + // force this AWT Canvas to be focus-able, + // since this it is completely covered by the newtChild (z-order). + setFocusable(true); } else { - configureNewtChild(false); - nativeWindow = null; + configureNewtChild(false); newtChild.setVisible(false); newtChild.reparentWindow(null); + if(null != jawtWindow) { + NewtFactoryAWT.destroyNativeWindow(jawtWindow); + jawtWindow=null; + } } } @@ -273,7 +419,10 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont); } configureNewtChild(false); - nativeWindow = null; + if(null!=jawtWindow) { + NewtFactoryAWT.destroyNativeWindow(jawtWindow); + jawtWindow=null; + } newtChild.setVisible(false); newtChild.reparentWindow(null); newtChild.destroy(); @@ -282,7 +431,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto cont.remove(this); } } - } + } @Override public void paint(Graphics g) { @@ -299,14 +448,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } } - final void requestFocusAWTParent() { - super.requestFocusInWindow(); - } - - final void requestFocusNEWTChild() { + private final void requestFocusNEWTChild() { if(null!=newtChild) { newtChild.setFocusAction(null); - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + if(isOnscreen) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } newtChild.requestFocus(); newtChild.setFocusAction(focusAction); } diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java index 2e86cb512..a052f6f97 100755 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java @@ -1,20 +1,48 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.newt.awt.applet; -import java.applet.*; +import java.applet.Applet; +import java.awt.BorderLayout; +import java.awt.Button; import java.awt.Component; import java.awt.Container; -import java.awt.Label; +import java.awt.event.KeyListener; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import java.awt.event.KeyListener; -import javax.media.opengl.*; +import javax.media.opengl.FPSCounter; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; import com.jogamp.newt.awt.NewtCanvasAWT; import com.jogamp.newt.opengl.GLWindow; -import java.awt.BorderLayout; - -import jogamp.newt.Debug; /** * Simple GLEventListener deployment as an applet using JOGL. This demo must be @@ -62,7 +90,7 @@ import jogamp.newt.Debug; */ @SuppressWarnings("serial") public class JOGLNewtApplet1Run extends Applet { - public static final boolean DEBUG = Debug.debug("Applet"); + public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG; GLWindow glWindow; NewtCanvasAWT newtCanvasAWT; @@ -72,6 +100,9 @@ public class JOGLNewtApplet1Run extends Applet { boolean glStandalone = false; public void init() { + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.init() START"); + } if(!(this instanceof Container)) { throw new RuntimeException("This Applet is not a AWT Container"); } @@ -88,6 +119,7 @@ public class JOGLNewtApplet1Run extends Applet { int glAlphaBits=0; int glNumMultisampleBuffer=0; boolean glNoDefaultKeyListener = false; + boolean appletDebugTestBorder = false; try { glEventListenerClazzName = getParameter("gl_event_listener_class"); glProfileName = getParameter("gl_profile"); @@ -104,6 +136,7 @@ public class JOGLNewtApplet1Run extends Applet { glWidth = JOGLNewtAppletBase.str2Int(getParameter("gl_width"), glWidth); glHeight = JOGLNewtAppletBase.str2Int(getParameter("gl_height"), glHeight); glNoDefaultKeyListener = JOGLNewtAppletBase.str2Bool(getParameter("gl_nodefaultkeyListener"), glNoDefaultKeyListener); + appletDebugTestBorder = JOGLNewtAppletBase.str2Bool(getParameter("appletDebugTestBorder"), appletDebugTestBorder); } catch (Exception e) { e.printStackTrace(); } @@ -137,7 +170,6 @@ public class JOGLNewtApplet1Run extends Applet { glTrace); try { - GLProfile.initSingleton(false); GLCapabilities caps = new GLCapabilities(GLProfile.get(glProfileName)); caps.setAlphaBits(glAlphaBits); if(0<glNumMultisampleBuffer) { @@ -149,18 +181,12 @@ public class JOGLNewtApplet1Run extends Applet { glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err); glWindow.setUndecorated(glUndecorated); glWindow.setAlwaysOnTop(glAlwaysOnTop); - if(glStandalone) { - newtCanvasAWT = null; - } else { - newtCanvasAWT = new NewtCanvasAWT(glWindow); - container.setLayout(new BorderLayout()); - container.add(newtCanvasAWT, BorderLayout.CENTER); - } - if(DEBUG) { - container.add(new Label("North"), BorderLayout.NORTH); - container.add(new Label("South"), BorderLayout.SOUTH); - container.add(new Label("East"), BorderLayout.EAST); - container.add(new Label("West"), BorderLayout.WEST); + container.setLayout(new BorderLayout()); + if(appletDebugTestBorder) { + container.add(new Button("North"), BorderLayout.NORTH); + container.add(new Button("South"), BorderLayout.SOUTH); + container.add(new Button("East"), BorderLayout.EAST); + container.add(new Button("West"), BorderLayout.WEST); } base.init(glWindow); if(base.isValid()) { @@ -176,12 +202,25 @@ public class JOGLNewtApplet1Run extends Applet { addKeyListener((KeyListener)glEventListener); } } + if(glStandalone) { + newtCanvasAWT = null; + } else { + newtCanvasAWT = new NewtCanvasAWT(glWindow); + container.add(newtCanvasAWT, BorderLayout.CENTER); + container.validate(); + } } catch (Throwable t) { throw new RuntimeException(t); } + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.init() END"); + } } public void start() { + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.start() START"); + } this.validate(); this.setVisible(true); @@ -195,21 +234,35 @@ public class JOGLNewtApplet1Run extends Applet { while (null != topC.getParent()) { topC = topC.getParent(); } + System.err.println("JOGLNewtApplet1Run start:"); System.err.println("TopComponent: "+topC.getLocation()+" rel, "+topC.getLocationOnScreen()+" screen, visible "+topC.isVisible()+", "+topC); System.err.println("Applet Pos: "+this.getLocation()+" rel, "+p0+" screen, visible "+this.isVisible()+", "+this); if(null != newtCanvasAWT) { System.err.println("NewtCanvasAWT Pos: "+newtCanvasAWT.getLocation()+" rel, "+newtCanvasAWT.getLocationOnScreen()+" screen, visible "+newtCanvasAWT.isVisible()+", "+newtCanvasAWT); } System.err.println("GLWindow Pos: "+glWindow.getX()+"/"+glWindow.getY()+" rel, "+glWindow.getLocationOnScreen(null)+" screen"); + System.err.println("GLWindow: "+glWindow); } base.start(); + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.start() END"); + } } public void stop() { + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.stop() START"); + } base.stop(); + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.stop() END"); + } } public void destroy() { + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.destroy() START"); + } glWindow.setVisible(false); // hide 1st if(!glStandalone) { glWindow.reparentWindow(null); // get out of newtCanvasAWT @@ -217,6 +270,9 @@ public class JOGLNewtApplet1Run extends Applet { } base.destroy(); // destroy glWindow unrecoverable base=null; + if(DEBUG) { + System.err.println("JOGLNewtApplet1Run.destroy() END"); + } } } diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java index b1061dd14..67da50210 100755 --- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java +++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java @@ -1,18 +1,53 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ package com.jogamp.newt.awt.applet; -import java.lang.reflect.*; +import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; import javax.media.nativewindow.NativeWindow; -import javax.media.opengl.*; +import javax.media.opengl.FPSCounter; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; import jogamp.newt.Debug; -import com.jogamp.opengl.util.*; - -import com.jogamp.newt.event.*; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowListener; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + /** Shows how to deploy an applet using JOGL. This demo must be referenced from a web page via an <applet> tag. */ @@ -165,6 +200,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener { public void start() { if(isValid) { glWindow.setVisible(true); + glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); glAnimator.start(); awtParent = glWindow.getParent(); } diff --git a/src/newt/classes/com/jogamp/newt/event/InputEvent.java b/src/newt/classes/com/jogamp/newt/event/InputEvent.java index 51ceccf31..d8a9235c1 100644 --- a/src/newt/classes/com/jogamp/newt/event/InputEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/InputEvent.java @@ -48,6 +48,11 @@ public abstract class InputEvent extends NEWTEvent public static final int CONFINED_MASK = 1 << 16; public static final int INVISIBLE_MASK = 1 << 17; + /** Object when attached via {@link #setAttachment(Object)} marks the event consumed, + * ie. stops propagating the event any further to the event listener. + */ + public static final Object consumedTag = new Object(); + protected InputEvent(int eventType, Object source, long when, int modifiers) { super(eventType, source, when); this.modifiers=modifiers; diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 9e4fe372b..44fcea49c 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -34,6 +34,7 @@ package com.jogamp.newt.event; +@SuppressWarnings("serial") public class KeyEvent extends InputEvent { public KeyEvent(int eventType, Object source, long when, int modifiers, int keyCode, char keyChar) { @@ -42,9 +43,12 @@ public class KeyEvent extends InputEvent this.keyChar=keyChar; } + /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */ public char getKeyChar() { return keyChar; } + + /** Always valid. */ public int getKeyCode() { return keyCode; } diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java index ccc674f1d..9bc3be1e5 100644 --- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java @@ -139,6 +139,20 @@ public class MouseEvent extends InputEvent return pressure[index]; } + /** + * <i>Usually</i> a wheel rotation of <b>> 0 is up</b>, + * and <b>< 0 is down</b>.<br> + * <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior. + * The latter is true for OS X 10.7 (Lion) for example. + * <p> + * The events will be send usually in steps of one, ie. <i>-1</i> and <i>1</i>. + * Higher values may result due to fast scrolling. + * </p> + * <p> + * The button number refers to the wheel number. + * </p> + * @return + */ public int getWheelRotation() { return wheelRotation; } diff --git a/src/newt/classes/com/jogamp/newt/event/MouseListener.java b/src/newt/classes/com/jogamp/newt/event/MouseListener.java index 5ec086b94..7668b755c 100644 --- a/src/newt/classes/com/jogamp/newt/event/MouseListener.java +++ b/src/newt/classes/com/jogamp/newt/event/MouseListener.java @@ -43,6 +43,8 @@ public interface MouseListener extends NEWTEventListener public void mouseReleased(MouseEvent e); public void mouseMoved(MouseEvent e); public void mouseDragged(MouseEvent e); + + /** See {@link MouseEvent#getWheelRotation() } */ public void mouseWheelMoved(MouseEvent e); } diff --git a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java index 50aed2c8e..3f3817b91 100644 --- a/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/NEWTEvent.java @@ -46,6 +46,7 @@ package com.jogamp.newt.event; * <li> KeyEvent <code>300..30x</code></li> * </ul><br> */ +@SuppressWarnings("serial") public class NEWTEvent extends java.util.EventObject { private final boolean isSystemEvent; private final int eventType; diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index ae7474c73..69b0d0482 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -107,6 +107,9 @@ public class AWTWindowAdapter public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWT: componentResized: "+event); + } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowResized(event); } else { @@ -116,6 +119,9 @@ public class AWTWindowAdapter public void componentMoved(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWT: componentMoved: "+event); + } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowMoved(event); } else { diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 2cd8c2ced..92f57577d 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -41,6 +41,7 @@ import com.jogamp.common.GlueGenVersion; import com.jogamp.common.util.VersionUtil; import com.jogamp.newt.*; import com.jogamp.newt.event.*; + import jogamp.newt.WindowImpl; import javax.media.nativewindow.*; @@ -54,8 +55,8 @@ import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.util.Animator; /** - * An implementation of {@link javax.media.opengl.GLAutoDrawable} interface, - * using an aggregation of a {@link com.jogamp.newt.Window} implementation. + * An implementation of {@link GLAutoDrawable} and {@link Window} interface, + * using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed). * <P> * This implementation does not make the OpenGL context current<br> * before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br> @@ -121,12 +122,13 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC } /** - * Creates a new GLWindow attaching a new Window referencing a new Screen - * with the given GLCapabilities. - * <P> - * The resulting GLWindow owns the Window, Screen and Device, ie it will be destructed. - * <P> - * The default display connection will be used and reused if already in process. + * Creates a new GLWindow attaching a new Window referencing a + * new default Screen and default Display with the given GLCapabilities. + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> + * The default Display will be reused if already instantiated. */ public static GLWindow create(GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(caps)); @@ -135,8 +137,10 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC /** * Creates a new GLWindow attaching a new Window referencing the given Screen * with the given GLCapabilities. - * <P> - * The resulting GLWindow owns the Window, ie it will be destructed. + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> */ public static GLWindow create(Screen screen, GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(screen, caps)); @@ -144,8 +148,10 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC /** * Creates a new GLWindow attaching the given window. - * <P> - * The resulting GLWindow does not own the given Window, ie it will not be destructed. + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> */ public static GLWindow create(Window window) { return new GLWindow(window); @@ -154,11 +160,15 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC /** * Creates a new GLWindow attaching a new child Window * of the given <code>parentNativeWindow</code> with the given GLCapabilities. - * <P> + * <p> * The Display/Screen will be compatible with the <code>parentNativeWindow</code>, * or even identical in case it's a Newt Window. - * <P> - * The resulting GLWindow owns the Window, ie it will be destructed. + * An already instantiated compatible Display will be reused. + * </p> + * <p> + * The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} + * and {@link Screen#removeReference()}. + * </p> */ public static GLWindow create(NativeWindow parentNativeWindow, GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(parentNativeWindow, caps)); @@ -195,8 +205,8 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC return window.getRequestedCapabilities(); } - public final Window getWindow() { - return window; + public final Window getDelegatedWindow() { + return window.getDelegatedWindow(); } public final NativeWindow getParent() { @@ -254,10 +264,18 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC window.setFocusAction(focusAction); } + public void setKeyboardFocusHandler(KeyListener l) { + window.setKeyboardFocusHandler(l); + } + public final void requestFocus() { window.requestFocus(); } + public final void requestFocus(boolean wait) { + window.requestFocus(wait); + } + public boolean hasFocus() { return window.hasFocus(); } @@ -288,7 +306,7 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC @Override public final String toString() { return "NEWT-GLWindow[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + - ", \n\tContext: " + context + /** ", \n\tWindow: "+window+", \n\tFactory: "+factory+ */ "]"; + ", \n\tContext: " + context + ", \n\tWindow: "+window+ /** ", \n\tFactory: "+factory+ */ "]"; } public final int reparentWindow(NativeWindow newParent) { @@ -337,14 +355,6 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC // Hide methods here .. protected class GLLifecycleHook implements WindowImpl.LifecycleHook { - private class DisposeAction implements Runnable { - public final void run() { - // Lock: Covered by DestroyAction .. - helper.dispose(GLWindow.this); - } - } - DisposeAction disposeAction = new DisposeAction(); - public synchronized void destroyActionPreLock() { // nop } @@ -362,11 +372,10 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. try { - helper.invokeGL(drawable, context, disposeAction, null); + helper.disposeGL(GLWindow.this, drawable, context, null); } catch (GLException gle) { gle.printStackTrace(); } - context.destroy(); } drawable.setRealized(false); } @@ -399,11 +408,11 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) { NativeWindow nw; if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getPrivateGraphicsConfiguration()); } else { nw = window; } - GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) nw.getGraphicsConfiguration().getChosenCapabilities(); if(null==factory) { factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); } @@ -753,18 +762,6 @@ public class GLWindow implements GLAutoDrawable, Window, NEWTEventConsumer, FPSC window.runOnEDTIfAvail(wait, task); } - public final SurfaceUpdatedListener getSurfaceUpdatedListener(int index) { - return window.getSurfaceUpdatedListener(index); - } - - public final SurfaceUpdatedListener[] getSurfaceUpdatedListeners() { - return window.getSurfaceUpdatedListeners(); - } - - public final void removeAllSurfaceUpdatedListener() { - window.removeAllSurfaceUpdatedListener(); - } - public final void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { window.removeSurfaceUpdatedListener(l); } diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java index c7780b0d8..e71ef75ec 100644 --- a/src/newt/classes/com/jogamp/newt/util/MainThread.java +++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java @@ -93,17 +93,21 @@ import jogamp.newt.NEWTJNILibLoader; */ public class MainThread { private static final String MACOSXDisplayClassName = "jogamp.newt.driver.macosx.MacDisplay"; + private static final Platform.OSType osType; + private static final boolean isMacOSX; + /** if true, use the main thread EDT, otherwise AWT's EDT */ public static final boolean HINT_USE_MAIN_THREAD; static { final AccessControlContext localACC = AccessController.getContext(); - Platform.initSingleton(); NativeWindowFactory.initSingleton(true); NEWTJNILibLoader.loadNEWT(); HINT_USE_MAIN_THREAD = !NativeWindowFactory.isAWTAvailable() || - Debug.getBooleanProperty("newt.MainThread.force", true, localACC); + Debug.getBooleanProperty("newt.MainThread.force", true, localACC); + osType = Platform.getOSType(); + isMacOSX = osType == Platform.OSType.MACOS; } public static boolean useMainThread = false; @@ -132,7 +136,7 @@ public class MainThread { try { Class<?> mainClass = ReflectionUtil.getClass(mainClassName, true, getClass().getClassLoader()); if(null==mainClass) { - throw new RuntimeException(new ClassNotFoundException("MainThread couldn't find main class "+mainClassName)); + throw new RuntimeException(new ClassNotFoundException("MainAction couldn't find main class "+mainClassName)); } try { mainClassMain = mainClass.getDeclaredMethod("main", new Class[] { String[].class }); @@ -151,8 +155,23 @@ public class MainThread { if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin"); if ( useMainThread ) { - if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainThread fin - stop"); - System.exit(0); + if(isMacOSX) { + try { + if(DEBUG) { + System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0"); + } + ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication", + null, null, MainThread.class.getClassLoader()); + if(DEBUG) { + System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)"); + System.exit(0); + } } } } @@ -164,9 +183,6 @@ public class MainThread { useMainThread = HINT_USE_MAIN_THREAD; - final Platform.OSType osType = Platform.getOSType(); - final boolean isMacOSX = osType == Platform.OSType.MACOS; - if(DEBUG) { System.err.println("MainThread.main(): "+cur.getName()+ ", useMainThread "+ useMainThread + diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java index 5a8bf5bf2..8104f207a 100644 --- a/src/newt/classes/com/jogamp/newt/util/MonitorMode.java +++ b/src/newt/classes/com/jogamp/newt/util/MonitorMode.java @@ -43,8 +43,9 @@ public class MonitorMode { int refreshRate; public MonitorMode(SurfaceSize surfaceSize, DimensionImmutable screenSizeMM, int refreshRate) { - if(null==surfaceSize || refreshRate<=0) { - throw new IllegalArgumentException("surfaceSize must be set and refreshRate greater 0"); + // Don't validate screenSizeMM and refreshRate, since they may not be supported by the OS + if(null==surfaceSize) { + throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")"); } this.surfaceSize=surfaceSize; this.screenSizeMM=screenSizeMM; diff --git a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java index 1f5d5dd3d..78707e7cf 100644 --- a/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java +++ b/src/newt/classes/jogamp/newt/NEWTJNILibLoader.java @@ -43,6 +43,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import com.jogamp.common.jvm.JNILibLoaderBase; +import com.jogamp.common.os.Platform; import com.jogamp.common.util.cache.TempJarCache; public class NEWTJNILibLoader extends JNILibLoaderBase { @@ -50,9 +51,10 @@ public class NEWTJNILibLoader extends JNILibLoaderBase { public static void loadNEWT() { AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { + Platform.initSingleton(); final String libName = "newt"; if(TempJarCache.isInitialized() && null == TempJarCache.findLibrary(libName)) { - addNativeJarLibs(NEWTJNILibLoader.class, "jogl.all", "jogl-all", new String[] { "nativewindow", "newt" } ); + addNativeJarLibs(NEWTJNILibLoader.class, "jogl-all", new String[] { "nativewindow", "newt" } ); } loadLibrary(libName, false); return null; diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index fa7bafe5b..050e24b6c 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -48,18 +48,16 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { static long nextWindowHandle = 0x100; // start here - a marker protected void createNativeImpl() { - if(0!=getParentWindowHandle()) { - throw new NativeWindowException("OffscreenWindow does not support window parenting"); - } if(capsRequested.isOnscreen()) { throw new NativeWindowException("Capabilities is onscreen"); } - AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - config = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( - capsRequested, capsRequested, capabilitiesChooser, aScreen); - if (config == null) { + final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( + capsRequested, capsRequested, capabilitiesChooser, aScreen); + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); synchronized(OffscreenWindow.class) { setWindowHandle(nextWindowHandle++); @@ -70,6 +68,10 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { // nop } + public void surfaceSizeChanged(int width, int height) { + sizeChanged(false, width, height, false); + } + @Override public synchronized void destroy() { super.destroy(); @@ -89,29 +91,30 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { } @Override - public void setSize(int width, int height) { - if(!isVisible()) { - sizeChanged(false, width, height, false); - } - } - @Override public void setPosition(int x, int y) { // nop } + @Override public boolean setFullscreen(boolean fullscreen) { // nop return false; } - + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { sizeChanged(false, width, height, false); - visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); } else { - shouldNotCallThis(); + /** + * silently ignore: + FLAG_CHANGE_PARENTING + FLAG_CHANGE_DECORATION + FLAG_CHANGE_FULLSCREEN + FLAG_CHANGE_ALWAYSONTOP + */ } - return false; + return true; } @Override diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java index 9c51fe973..575de6112 100644 --- a/src/newt/classes/jogamp/newt/ScreenImpl.java +++ b/src/newt/classes/jogamp/newt/ScreenImpl.java @@ -34,6 +34,21 @@ package jogamp.newt; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.Point; +import javax.media.nativewindow.util.SurfaceSize; + import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.IntIntHashMap; import com.jogamp.newt.Display; @@ -44,14 +59,6 @@ import com.jogamp.newt.event.ScreenModeListener; import com.jogamp.newt.util.MonitorMode; import com.jogamp.newt.util.ScreenModeUtil; -import javax.media.nativewindow.*; -import javax.media.nativewindow.util.DimensionImmutable; -import javax.media.nativewindow.util.SurfaceSize; - -import java.security.*; -import java.util.ArrayList; -import java.util.List; - public abstract class ScreenImpl extends Screen implements ScreenModeListener { protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true); @@ -61,8 +68,10 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { protected int hashCode; protected AbstractGraphicsScreen aScreen; protected int refCount; // number of Screen references by Window - protected int width=-1, height=-1; // detected values: set using setScreenSize - protected static int usrWidth=-1, usrHeight=-1; // property values: newt.ws.swidth and newt.ws.sheight + protected Point vOrigin = new Point(0, 0); // virtual top-left origin + protected Dimension vSize = new Dimension(0, 0); // virtual rotated screen size + protected static Dimension usrSize = null; // property values: newt.ws.swidth and newt.ws.sheight + protected static volatile boolean usrSizeQueried = false; private static AccessControlContext localACC = AccessController.getContext(); private ArrayList<ScreenModeListener> referencedScreenModeListener = new ArrayList<ScreenModeListener>(); long t0; // creationTime @@ -100,32 +109,36 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { return (Class<? extends Screen>)screenClass; } - public static Screen create(Display display, final int idx) { + public static Screen create(Display display, int idx) { try { - if(usrWidth<0 || usrHeight<0) { + if(!usrSizeQueried) { synchronized (Screen.class) { - if(usrWidth<0 || usrHeight<0) { - usrWidth = Debug.getIntProperty("newt.ws.swidth", true, localACC); - usrHeight = Debug.getIntProperty("newt.ws.sheight", true, localACC); - if(usrWidth>0 || usrHeight>0) { - System.err.println("User screen size "+usrWidth+"x"+usrHeight); + if(!usrSizeQueried) { + usrSizeQueried = true; + final int w = Debug.getIntProperty("newt.ws.swidth", true, localACC); + final int h = Debug.getIntProperty("newt.ws.sheight", true, localACC); + if(w>0 && h>0) { + usrSize = new Dimension(w, h); + System.err.println("User screen size "+usrSize); } } } } synchronized(screenList) { + Class<? extends Screen> screenClass = getScreenClass(display.getType()); + ScreenImpl screen = (ScreenImpl) screenClass.newInstance(); + screen.display = (DisplayImpl) display; + idx = screen.validateScreenIndex(idx); { Screen screen0 = ScreenImpl.getLastScreenOf(display, idx, -1); if(null != screen0) { if(DEBUG) { System.err.println("Screen.create() REUSE: "+screen0+" "+Display.getThreadName()); } + screen = null; return screen0; } } - Class<? extends Screen> screenClass = getScreenClass(display.getType()); - ScreenImpl screen = (ScreenImpl) screenClass.newInstance(); - screen.display = (DisplayImpl) display; screen.screen_idx = idx; screen.fqname = (display.getFQName()+idx).intern(); screen.hashCode = screen.fqname.hashCode(); @@ -176,6 +189,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); } initScreenModeStatus(); + updateVirtualScreenOriginAndSize(); if(DEBUG) { System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+")"); } @@ -208,6 +222,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { public synchronized final int addReference() throws NativeWindowException { if(DEBUG) { System.err.println("Screen.addReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount+1)); + // Thread.dumpStack(); } if ( 0 == refCount ) { createNative(); @@ -220,10 +235,8 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { public synchronized final int removeReference() { if(DEBUG) { - String msg = "Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1); - // Throwable t = new Throwable(msg); - // t.printStackTrace(); - System.err.println(msg); + System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1)); + // Thread.dumpStack(); } refCount--; // could become < 0, in case of manual destruction without actual creation/addReference if(0>=refCount) { @@ -239,19 +252,37 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { protected abstract void createNativeImpl(); protected abstract void closeNativeImpl(); - + + /** + * Returns the validated screen index, which is either the passed <code>idx</code> + * value or <code>0</code>. + * <p> + * On big-desktops this shall return always 0. + * </p> + */ + protected abstract int validateScreenIndex(int idx); + + /** + * Stores the virtual origin and virtual <b>rotated</b> screen size. + * <p> + * This method is called after the ScreenMode has been set, + * hence you may utilize it. + * </p> + * @param virtualOrigin the store for the virtual origin + * @param virtualSize the store for the virtual rotated size + */ + protected abstract void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize); + public final String getFQName() { return fqname; } /** - * Set the <b>rotated</b> ScreenSize. - * @see com.jogamp.newt.ScreenMode#getRotatedWidth() - * @see com.jogamp.newt.ScreenMode#getRotatedHeight() + * Updates the <b>rotated</b> virtual ScreenSize using the native impl. */ - protected void setScreenSize(int w, int h) { - System.err.println("Detected screen size "+w+"x"+h); - width=w; height=h; + protected void updateVirtualScreenOriginAndSize() { + getVirtualScreenOriginAndSize(vOrigin, vSize); + System.err.println("Detected screen origin "+vOrigin+", size "+vSize); } public final Display getDisplay() { @@ -270,21 +301,15 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { return null != aScreen; } + public int getX() { return vOrigin.getX(); } + public int getY() { return vOrigin.getY(); } - /** - * @return the <b>rotated</b> width. - * @see com.jogamp.newt.ScreenMode#getRotatedWidth() - */ public final int getWidth() { - return (usrWidth>0) ? usrWidth : (width>0) ? width : 480; + return (null != usrSize) ? usrSize.getWidth() : vSize.getWidth(); } - /** - * @return the <b>rotated</b> height - * @see com.jogamp.newt.ScreenMode#getRotatedHeight() - */ public final int getHeight() { - return (usrHeight>0) ? usrHeight : (height>0) ? height : 480; + return (null != usrSize) ? usrSize.getHeight() : vSize.getHeight(); } @Override @@ -347,32 +372,29 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { try { long t0=0, t1=0; if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.0 "+screenMode); + System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.0 "+smU); t0 = System.currentTimeMillis(); } sms.fireScreenModeChangeNotify(smU); if(DEBUG) { - System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.1 "+screenMode); + System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): 0.1 "+smU); t1 = System.currentTimeMillis(); } success = setCurrentScreenModeImpl(smU); - if(success) { - setScreenSize(screenMode.getRotatedWidth(), screenMode.getRotatedHeight()); - } if(DEBUG) { t1 = System.currentTimeMillis() - t1; - System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.0 "+screenMode+", success: "+success); + System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.0 "+smU+", success: "+success); } sms.fireScreenModeChanged(smU, success); if(DEBUG) { t0 = System.currentTimeMillis() - t0; - System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.X "+screenMode+", success: "+success+ + System.err.println("Screen.setCurrentScreenMode ("+(System.currentTimeMillis()-t0)+"): X.X "+smU+", success: "+success+ " - dt0 "+t0+"ms, dt1 "+t1+"ms"); } } finally { @@ -389,7 +411,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { public void screenModeChanged(ScreenMode sm, boolean success) { if(success) { - setScreenSize(sm.getRotatedWidth(), sm.getRotatedHeight()); + updateVirtualScreenOriginAndSize(); } for(int i=0; i<referencedScreenModeListener.size(); i++) { ((ScreenModeListener)referencedScreenModeListener.get(i)).screenModeChanged(sm, success); @@ -502,11 +524,12 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { } ArrayHashSet<ScreenMode> screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx); - if(screenModes.size()==0) { - if(DEBUG) { - System.err.println("ScreenImpl.initScreenModeStatus: added current (last resort, collect failed): "+currentSM); + screenModes.getOrAdd(currentSM); + if(DEBUG) { + int i=0; + for(Iterator<ScreenMode> iter=screenModes.iterator(); iter.hasNext(); i++) { + System.err.println(i+": "+iter.next()); } - screenModes.getOrAdd(currentSM); } sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx); @@ -550,9 +573,18 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener { int nativeId = smProps[0]; int screenModeIdx = ScreenModeUtil.streamIn(resolutionPool, surfaceSizePool, screenSizeMMPool, monitorModePool, screenModePool, smProps, 1); + if(DEBUG) { + System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": idx: "+nativeId+" native -> "+screenModeIdx+" newt"); + } + if(screenModeIdx >= 0) { screenModesIdx2NativeId.put(screenModeIdx, nativeId); } + } else if(DEBUG) { + System.err.println("ScreenImpl.collectNativeScreenModes: #"+num+": smProps: "+(null!=smProps)+ + ", len: "+(null != smProps ? smProps.length : 0)+ + ", bpp: "+(null != smProps && 0 < smProps.length ? smProps[idxBpp] : 0)+ + " - DROPPING"); } num++; } while ( null != smProps && 0 < smProps.length ); diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 7df326e8e..6564857e4 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -72,6 +72,8 @@ import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.Rectangle; +import jogamp.nativewindow.SurfaceUpdatedHelper; + public abstract class WindowImpl implements Window, NEWTEventConsumer { public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true); @@ -85,12 +87,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private boolean screenReferenceAdded = false; private NativeWindow parentWindow = null; private long parentWindowHandle = 0; - protected AbstractGraphicsConfiguration config = null; + private AbstractGraphicsConfiguration config = null; // control access due to delegation protected CapabilitiesImmutable capsRequested = null; protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default protected boolean fullscreen = false, hasFocus = false; protected int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user - protected int x = -1, y = -1; // client-area pos w/o insets, default: undefined (allow WM to choose if not set by user) + protected int x = 64, y = 64; // client-area pos w/o insets + protected boolean autoPosition = true; // default: true (allow WM to choose if not set by user) protected Insets insets = new Insets(); // insets of decoration (if top-level && decorated) protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets @@ -108,10 +111,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private RequestFocusAction requestFocusAction = new RequestFocusAction(); private FocusRunnable focusAction = null; + private KeyListener keyboardFocusHandler = null; - private Object surfaceUpdatedListenersLock = new Object(); - private ArrayList<SurfaceUpdatedListener> surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>(); - + private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + private Object childWindowsLock = new Object(); private ArrayList<NativeWindow> childWindows = new ArrayList<NativeWindow>(); @@ -213,6 +216,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } + protected final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) { + config = cfg; + } + public static interface LifecycleHook { /** * Reset of internal state counter, ie totalFrames, etc. @@ -270,8 +277,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindow.lockSurface() ) { throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow); } - if( ( 0>x || 0>y ) && ( isUndecorated() || null != parentWindow ) ) { - // default child/undecorated window position is 0/0, if not set by user + if( ( 0>x || 0>y ) && null != parentWindow ) { + // min. child window position is 0/0 x = 0; y = 0; } try { @@ -545,7 +552,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if ( LOCK_SURFACE_NOT_READY == res ) { try { if( isNativeValid() ) { - final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); adevice.lock(); try { res = lockSurfaceImpl(); @@ -570,7 +577,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer windowLock.validateLocked(); if (surfaceLock.getHoldCount() == 1) { - final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); try { unlockSurfaceImpl(); } finally { @@ -613,8 +620,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return false; } - public AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config; + public final AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config.getNativeGraphicsConfiguration(); } public final long getDisplayHandle() { @@ -682,6 +689,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return screen; } + protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) { + reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible)); + } final void setVisibleActionImpl(boolean visible) { boolean nativeWindowCreated = false; boolean madeVisible = false; @@ -740,8 +750,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( nativeWindowCreated || madeVisible ) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } - } - + } private class VisibleAction implements Runnable { boolean visible; @@ -752,8 +761,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public final void run() { setVisibleActionImpl(visible); } - } - + } public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window setVisible: START ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); @@ -762,59 +770,67 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer runOnEDTIfAvail(true, new VisibleAction(visible)); } - protected final void setVisibleImpl(boolean visible, int x, int y, int width, int height) { - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible)); + final void setSizeActionImpl(int width, int height) { + boolean recreate = false; + windowLock.lock(); + try { + int visibleAction = 0; // 1 invisible, 2 visible (create) + if ( !fullscreen && ( width != WindowImpl.this.width || WindowImpl.this.height != height ) ) { + recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setSize: START "+WindowImpl.this.width+"x"+WindowImpl.this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); + } + if(recreate) { + // will trigger visibleAction:=2 -> create if wasVisible + final boolean wasVisible = WindowImpl.this.visible; + screen.addReference(); // retain screen + destroyAction.run(); + WindowImpl.this.visible = wasVisible; + } + if ( isNativeValid() && 0>=width*height && visible ) { + visibleAction=1; // invisible + WindowImpl.this.width = 0; + WindowImpl.this.height = 0; + } else if ( !isNativeValid() && 0<width*height && visible ) { + visibleAction = 2; // visible (create) + WindowImpl.this.width = width; + WindowImpl.this.height = height; + } else if ( isNativeValid() ) { + // this width/height will be set by windowChanged, called by the native implementation + reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(0, isVisible())); + } else { + WindowImpl.this.width = width; + WindowImpl.this.height = height; + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setSize: END "+WindowImpl.this.width+"x"+WindowImpl.this.height+", visibleAction "+visibleAction); + } + switch(visibleAction) { + case 1: setVisibleActionImpl(false); break; + case 2: setVisibleActionImpl(true); break; + } + } + } finally { + if(recreate) { + screen.removeReference(); // bring back ref-count + } + windowLock.unlock(); + } } - - private class SetSizeActionImpl implements Runnable { + private class SetSizeAction implements Runnable { int width, height; - private SetSizeActionImpl(int w, int h) { + private SetSizeAction(int w, int h) { width = w; height = h; } public final void run() { - windowLock.lock(); - try { - int visibleAction = 0; // 1 invisible, 2 visible (create) - if ( !fullscreen && ( width != WindowImpl.this.width || WindowImpl.this.height != height ) ) { - if(DEBUG_IMPLEMENTATION) { - String msg = "Window setSize: START "+WindowImpl.this.width+"x"+WindowImpl.this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible; - System.err.println(msg); - } - if ( isNativeValid() && 0>=width*height && visible ) { - visibleAction=1; // invisible - WindowImpl.this.width = 0; - WindowImpl.this.height = 0; - } else if ( !isNativeValid() && 0<width*height && visible ) { - visibleAction = 2; // visible (create) - WindowImpl.this.width = width; - WindowImpl.this.height = height; - } else if ( isNativeValid() ) { - // this width/height will be set by windowChanged, called by the native implementation - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(0, isVisible())); - } else { - WindowImpl.this.width = width; - WindowImpl.this.height = height; - } - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: END "+WindowImpl.this.width+"x"+WindowImpl.this.height+", visibleAction "+visibleAction); - } - switch(visibleAction) { - case 1: setVisibleActionImpl(false); break; - case 2: setVisibleActionImpl(true); break; - } - } - } finally { - windowLock.unlock(); - } + setSizeActionImpl(width, height); } - } - + } public void setSize(int width, int height) { - runOnEDTIfAvail(true, new SetSizeActionImpl(width, height)); - } - + runOnEDTIfAvail(true, new SetSizeAction(width, height)); + } public void setTopLevelSize(int width, int height) { setSize(width - getInsets().getTotalWidth(), height - getInsets().getTotalHeight()); } @@ -911,6 +927,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer runOnEDTIfAvail(true, destroyAction); } + /** + * @param cWin child window, must not be null + * @param pWin parent window, may be null + * @return true if at least one of both window's configurations is offscreen + */ + protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) { + boolean ofs = false; + if( null != cWin.getGraphicsConfiguration() ) { + ofs = !cWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + } + if( !ofs && null != pWin && null != pWin.getGraphicsConfiguration() ) { + ofs |= !pWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + } + return ofs; + } + private class ReparentActionImpl implements Runnable, ReparentAction { NativeWindow newParentWindow; boolean forceDestroyCreate; @@ -918,7 +950,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private ReparentActionImpl(NativeWindow newParentWindow, boolean forceDestroyCreate) { this.newParentWindow = newParentWindow; - this.forceDestroyCreate = forceDestroyCreate; + this.forceDestroyCreate = forceDestroyCreate | DEBUG_TEST_REPARENT_INCOMPATIBLE; this.reparentAction = -1; // ensure it's set } @@ -927,10 +959,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } private void setScreen(ScreenImpl newScreen) { // never null ! - WindowImpl.this.removeScreenReference(); + removeScreenReference(); screen = newScreen; } - + public final void run() { boolean animatorPaused = false; if(null!=lifecycleHook) { @@ -952,6 +984,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer windowLock.lock(); try { + if(isNativeValid()) { + // force recreation if offscreen, since it may become onscreen + forceDestroyCreate |= isOffscreenInstance(WindowImpl.this, newParentWindow); + } + wasVisible = isVisible(); Window newParentWindowNEWT = null; @@ -962,7 +999,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer long newParentWindowHandle = 0 ; if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.reparent: START ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+" "+x+"/"+y+" "+width+"x"+height); + System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", visible "+wasVisible+", old parentWindow: "+Display.hashCodeNullSafe(parentWindow)+", new parentWindow: "+Display.hashCodeNullSafe(newParentWindow)+", forceDestroyCreate "+forceDestroyCreate+", "+x+"/"+y+" "+width+"x"+height); } if(null!=lifecycleHook) { @@ -1013,8 +1050,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } else { reparentAction = ACTION_NATIVE_CREATION_PENDING; } - } else if ( DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate || - !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) { + } else if ( forceDestroyCreate || !NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) { // Destroy this window, may create a new compatible Screen/Display, // and mark it for creation. destroy(); @@ -1045,7 +1081,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( 0 == parentWindowHandle ) { // Already Top Window reparentAction = ACTION_UNCHANGED; - } else if( !isNativeValid() || DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate ) { + } else if( !isNativeValid() || forceDestroyCreate ) { // Destroy this window and mark it for [pending] creation. destroy(); if( 0<width*height ) { @@ -1138,7 +1174,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW); } if(ok) { - requestFocusImpl(true); + requestFocusInt(true); display.dispatchMessagesNative(); // status up2date } } @@ -1208,7 +1244,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public int reparentWindow(NativeWindow newParent, boolean forceDestroyCreate) { - ReparentActionImpl reparentAction = new ReparentActionImpl(newParent, forceDestroyCreate); + final ReparentActionImpl reparentAction = new ReparentActionImpl(newParent, forceDestroyCreate); runOnEDTIfAvail(true, reparentAction); return reparentAction.getStrategy(); } @@ -1220,7 +1256,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final CapabilitiesImmutable getChosenCapabilities() { - return config.getNativeGraphicsConfiguration().getChosenCapabilities(); + return getGraphicsConfiguration().getChosenCapabilities(); } public final CapabilitiesImmutable getRequestedCapabilities() { @@ -1385,14 +1421,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void requestFocus() { - enqueueRequestFocus(true); - } - - public final boolean hasFocus() { - return hasFocus; - } - public final InsetsImmutable getInsets() { if(isUndecorated()) { return Insets.getZero(); @@ -1452,7 +1480,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public Object getWrappedWindow() { return null; } - + + public final Window getDelegatedWindow() { + return this; + } + /** * If set to true, the default value, this NEWT Window implementation will * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.<br> @@ -1466,6 +1498,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // WindowImpl // + /** + * Returns the non delegated {@link AbstractGraphicsConfiguration}, + * see {@link #getGraphicsConfiguration()}. */ + public final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { + return config; + } + protected final long getParentWindowHandle() { return isFullscreen() ? 0 : parentWindowHandle; } @@ -1487,9 +1526,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer "\n, WrappedWindow "+getWrappedWindow()+ "\n, ChildWindows "+childWindows.size()); - sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedListeners.size()+" ["); - for (int i = 0; i < surfaceUpdatedListeners.size(); i++ ) { - sb.append(surfaceUpdatedListeners.get(i)+", "); + sb.append(", SurfaceUpdatedListeners num "+surfaceUpdatedHelper.size()+" ["); + for (int i = 0; i < surfaceUpdatedHelper.size(); i++ ) { + sb.append(surfaceUpdatedHelper.get(i)+", "); } sb.append("], WindowListeners num "+windowListeners.size()+" ["); for (int i = 0; i < windowListeners.size(); i++ ) { @@ -1503,7 +1542,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer for (int i = 0; i < keyListeners.size(); i++ ) { sb.append(keyListeners.get(i)+", "); } - sb.append("] ]"); + sb.append("], surfaceLock "+surfaceLock); + sb.append(", windowLock "+windowLock+"]"); return sb.toString(); } @@ -1529,21 +1569,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - protected void enqueueRequestFocus(boolean wait) { - runOnEDTIfAvail(wait, requestFocusAction); + public final boolean hasFocus() { + return hasFocus; } - /** - * May set to a {@link FocusRunnable}, {@link FocusRunnable#run()} before Newt requests the native focus. - * This allows notifying a covered window toolkit like AWT that the focus is requested, - * hence focus traversal can be made transparent. - */ + public void requestFocus() { + requestFocus(true); + } + + public void requestFocus(boolean wait) { + if(isNativeValid() && !focusAction()) { + runOnEDTIfAvail(wait, requestFocusAction); + } + } + + /** Internal request focus on current thread */ + private void requestFocusInt(boolean force) { + if(!focusAction()) { + requestFocusImpl(force); + } + } + public void setFocusAction(FocusRunnable focusAction) { this.focusAction = focusAction; } - - /** Called by native requestFocusImpl() */ - protected boolean focusAction() { + + private boolean focusAction() { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.focusAction() START - "+getThreadName()+", focusAction: "+focusAction+" - windowHandle "+toHexString(getWindowHandle())); } @@ -1558,7 +1609,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } return res; } - + + public void setKeyboardFocusHandler(KeyListener l) { + keyboardFocusHandler = l; + } + private class SetPositionActionImpl implements Runnable { int x, y; @@ -1590,6 +1645,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public void setPosition(int x, int y) { + autoPosition = false; runOnEDTIfAvail(true, new SetPositionActionImpl(x, y)); } @@ -1622,7 +1678,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer nfs_y = WindowImpl.this.y; nfs_width = WindowImpl.this.width; nfs_height = WindowImpl.this.height; - x = 0; y = 0; + x = screen.getX(); + y = screen.getY(); w = screen.getWidth(); h = screen.getHeight(); } else { @@ -1680,7 +1737,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer display.dispatchMessagesNative(); // status up2date WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW); display.dispatchMessagesNative(); // status up2date - requestFocusImpl(true); + requestFocusInt(true); display.dispatchMessagesNative(); // status up2date if(DEBUG_IMPLEMENTATION) { @@ -1800,8 +1857,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // queue event in case window is locked, ie in operation if( isWindowLocked() ) { if(DEBUG_IMPLEMENTATION) { - // System.err.println("Window.consumeEvent: queued "+e); - // Thread.dumpStack(); // JAU + System.err.println("Window.consumeEvent: queued "+e); + // Thread.dumpStack(); } return false; } @@ -1824,62 +1881,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // // SurfaceUpdatedListener Support // - public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { - addSurfaceUpdatedListener(-1, l); + surfaceUpdatedHelper.addSurfaceUpdatedListener(l); } - public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) - throws IndexOutOfBoundsException - { - if(l == null) { - return; - } - synchronized(surfaceUpdatedListenersLock) { - if(0>index) { - index = surfaceUpdatedListeners.size(); - } - surfaceUpdatedListeners.add(index, l); - } + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); } public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { - if (l == null) { - return; - } - synchronized(surfaceUpdatedListenersLock) { - surfaceUpdatedListeners.remove(l); - } - } - - public void removeAllSurfaceUpdatedListener() { - synchronized(surfaceUpdatedListenersLock) { - surfaceUpdatedListeners = new ArrayList<SurfaceUpdatedListener>(); - } - } - - public SurfaceUpdatedListener getSurfaceUpdatedListener(int index) { - synchronized(surfaceUpdatedListenersLock) { - if(0>index) { - index = surfaceUpdatedListeners.size()-1; - } - return surfaceUpdatedListeners.get(index); - } - } - - public SurfaceUpdatedListener[] getSurfaceUpdatedListeners() { - synchronized(surfaceUpdatedListenersLock) { - return (SurfaceUpdatedListener[]) surfaceUpdatedListeners.toArray(); - } + surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); } public void surfaceUpdated(Object updater, NativeSurface ns, long when) { - synchronized(surfaceUpdatedListenersLock) { - for(int i = 0; i < surfaceUpdatedListeners.size(); i++ ) { - SurfaceUpdatedListener l = surfaceUpdatedListeners.get(i); - l.surfaceUpdated(updater, ns, when); - } - } + surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); } // @@ -1893,8 +1908,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer int x, int y, int button, int rotation) { doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotation); } - private void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, - int x, int y, int button, int rotation) { + + protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, + int x, int y, int button, int rotation) { if(eventType == MouseEvent.EVENT_MOUSE_ENTERED || eventType == MouseEvent.EVENT_MOUSE_EXITED) { if(eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1) { @@ -2026,15 +2042,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public MouseListener[] getMouseListeners() { - return (MouseListener[]) mouseListeners.toArray(); + return mouseListeners.toArray(new MouseListener[mouseListeners.size()]); } protected void consumeMouseEvent(MouseEvent e) { if(DEBUG_MOUSE_EVENT) { System.err.println("consumeMouseEvent: event: "+e); } - - for(int i = 0; i < mouseListeners.size(); i++ ) { + boolean consumed = false; + for(int i = 0; !consumed && i < mouseListeners.size(); i++ ) { MouseListener l = mouseListeners.get(i); switch(e.getEventType()) { case MouseEvent.EVENT_MOUSE_CLICKED: @@ -2064,13 +2080,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer default: throw new NativeWindowException("Unexpected mouse event type " + e.getEventType()); } + consumed = InputEvent.consumedTag == e.getAttachment(); } } // // KeyListener/Event Support // - public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { consumeKeyEvent(new KeyEvent(eventType, this, System.currentTimeMillis(), modifiers, keyCode, keyChar) ); } @@ -2116,29 +2132,42 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public KeyListener[] getKeyListeners() { - return (KeyListener[]) keyListeners.toArray(); + return keyListeners.toArray(new KeyListener[keyListeners.size()]); } - protected void consumeKeyEvent(KeyEvent e) { - if(DEBUG_KEY_EVENT) { - System.err.println("consumeKeyEvent: "+e); + private final boolean propagateKeyEvent(KeyEvent e, KeyListener l) { + switch(e.getEventType()) { + case KeyEvent.EVENT_KEY_PRESSED: + l.keyPressed(e); + break; + case KeyEvent.EVENT_KEY_RELEASED: + l.keyReleased(e); + break; + case KeyEvent.EVENT_KEY_TYPED: + l.keyTyped(e); + break; + default: + throw new NativeWindowException("Unexpected key event type " + e.getEventType()); } - for(int i = 0; i < keyListeners.size(); i++ ) { - KeyListener l = keyListeners.get(i); - switch(e.getEventType()) { - case KeyEvent.EVENT_KEY_PRESSED: - l.keyPressed(e); - break; - case KeyEvent.EVENT_KEY_RELEASED: - l.keyReleased(e); - break; - case KeyEvent.EVENT_KEY_TYPED: - l.keyTyped(e); - break; - default: - throw new NativeWindowException("Unexpected key event type " + e.getEventType()); + return InputEvent.consumedTag == e.getAttachment(); + } + + protected void consumeKeyEvent(KeyEvent e) { + boolean consumed; + if(null != keyboardFocusHandler) { + consumed = propagateKeyEvent(e, keyboardFocusHandler); + if(DEBUG_KEY_EVENT) { + System.err.println("consumeKeyEvent: "+e+", keyboardFocusHandler consumed: "+consumed); + } + } else { + consumed = false; + if(DEBUG_KEY_EVENT) { + System.err.println("consumeKeyEvent: "+e); } } + for(int i = 0; !consumed && i < keyListeners.size(); i++ ) { + consumed = propagateKeyEvent(e, keyListeners.get(i)); + } } // @@ -2191,7 +2220,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public WindowListener[] getWindowListeners() { - return (WindowListener[]) windowListeners.toArray(); + return windowListeners.toArray(new WindowListener[windowListeners.size()]); } protected void consumeWindowEvent(WindowEvent e) { @@ -2324,6 +2353,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Triggered by implementation's WM events to update the position. */ protected void positionChanged(boolean defer, int newX, int newY) { + autoPosition = false; if ( x != newX || y != newY ) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.positionChanged: ("+getThreadName()+"): (defer: "+defer+") "+x+"/"+y+" -> "+newX+"/"+newY+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); @@ -2389,8 +2419,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * Triggered by implementation's WM events to update the content */ protected void windowRepaint(boolean defer, int x, int y, int width, int height) { - x = ( 0 > x ) ? this.x : x; - y = ( 0 > y ) ? this.y : y; width = ( 0 >= width ) ? this.width : width; height = ( 0 >= height ) ? this.height : height; if(DEBUG_IMPLEMENTATION) { diff --git a/src/newt/classes/jogamp/newt/awt/event/NewtFactoryAWT.java b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java index aa98d3a37..2ca3d2cfd 100644 --- a/src/newt/classes/jogamp/newt/awt/event/NewtFactoryAWT.java +++ b/src/newt/classes/jogamp/newt/awt/NewtFactoryAWT.java @@ -26,15 +26,19 @@ * or implied, of JogAmp Community. */ +package jogamp.newt.awt; -package jogamp.newt.awt.event; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; - -import javax.media.nativewindow.*; -import javax.media.nativewindow.awt.*; +import jogamp.nativewindow.jawt.JAWTWindow; +import jogamp.newt.Debug; import com.jogamp.newt.NewtFactory; -import jogamp.newt.Debug; public class NewtFactoryAWT extends NewtFactory { public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); @@ -51,7 +55,7 @@ public class NewtFactoryAWT extends NewtFactory { * * @param awtCompObject must be of type java.awt.Component */ - public static NativeWindow getNativeWindow(Object awtCompObject, CapabilitiesImmutable capsRequested) { + public static JAWTWindow getNativeWindow(Object awtCompObject, CapabilitiesImmutable capsRequested) { if(null==awtCompObject) { throw new NativeWindowException("Null AWT Component"); } @@ -61,13 +65,23 @@ public class NewtFactoryAWT extends NewtFactory { return getNativeWindow( (java.awt.Component) awtCompObject, capsRequested ); } - public static NativeWindow getNativeWindow(java.awt.Component awtComp, CapabilitiesImmutable capsRequested) { - DefaultGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, capsRequested, capsRequested); - NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + public static JAWTWindow getNativeWindow(java.awt.Component awtComp, CapabilitiesImmutable capsRequested) { + AWTGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, null, capsRequested); + NativeWindow nw = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + if(! ( nw instanceof JAWTWindow ) ) { + throw new NativeWindowException("Not an AWT NativeWindow: "+nw); + } if(DEBUG_IMPLEMENTATION) { - System.err.println("NewtFactoryAWT.getNativeWindow: "+awtComp+" -> "+awtNative); + System.err.println("NewtFactoryAWT.getNativeWindow: "+awtComp+" -> "+nw); } - return awtNative; + return (JAWTWindow)nw; + } + + public static void destroyNativeWindow(JAWTWindow jawtWindow) { + final AbstractGraphicsConfiguration config = jawtWindow.getGraphicsConfiguration(); + jawtWindow.destroy(); + config.getScreen().getDevice().close(); } + } diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index 358864547..8e9c028d4 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -28,6 +28,10 @@ package jogamp.newt.awt.event; +import java.awt.KeyboardFocusManager; + +import jogamp.newt.driver.DriverUpdatePosition; + import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; @@ -54,9 +58,16 @@ public class AWTParentWindowAdapter } public void focusGained(java.awt.event.FocusEvent e) { + // forward focus to NEWT child + final com.jogamp.newt.Window newtChild = getNewtWindow(); + final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("AWT: focusGained: "+ e); + System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e); + } + if(isOnscreen) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); } + newtChild.requestFocus(false); } public void focusLost(java.awt.event.FocusEvent e) { @@ -90,7 +101,12 @@ public class AWTParentWindowAdapter } public void componentMoved(java.awt.event.ComponentEvent e) { - // no propagation to NEWT child window + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWT: componentMoved: "+e); + } + if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) { + ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition(); + } } public void windowActivated(java.awt.event.WindowEvent e) { @@ -104,11 +120,11 @@ public class AWTParentWindowAdapter public void hierarchyChanged(java.awt.event.HierarchyEvent e) { if( null == getNewtEventListener() ) { long bits = e.getChangeFlags(); - final java.awt.Component changed = e.getChanged(); + final java.awt.Component changed = e.getChanged(); if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) { final boolean showing = changed.isShowing(); if(DEBUG_IMPLEMENTATION) { - System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); + System.err.println("AWT: hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed+", source "+e.getComponent()); } getNewtWindow().runOnEDTIfAvail(false, new Runnable() { public void run() { diff --git a/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java new file mode 100644 index 000000000..0a824e83b --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/DriverClearFocus.java @@ -0,0 +1,12 @@ +package jogamp.newt.driver; + +/** + * Interface tagging driver requirement of clearing the focus. + * <p> + * Some drivers require a programmatic {@link #clearFocus()} when traversing the focus. + * </p> + */ +public interface DriverClearFocus { + /** Programmatic clear the focus */ + void clearFocus(); +} diff --git a/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java new file mode 100644 index 000000000..bb846c081 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/DriverUpdatePosition.java @@ -0,0 +1,9 @@ +package jogamp.newt.driver; + +/** + * Interface tagging driver requirement of absolute positioning, ie. depend on parent position. + */ +public interface DriverUpdatePosition { + /** Programmatic update the position */ + void updatePosition(); +} diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java b/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java index ce6a9c594..e108ed0bb 100644 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java +++ b/src/newt/classes/jogamp/newt/driver/android/AndroidScreen.java @@ -29,6 +29,8 @@ package jogamp.newt.driver.android; import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; import com.jogamp.newt.ScreenMode; import com.jogamp.newt.util.ScreenModeUtil; @@ -74,6 +76,18 @@ public class AndroidScreen extends jogamp.newt.ScreenImpl { return ScreenModeUtil.streamIn(props, 0); } + protected int validateScreenIndex(int idx) { + return 0; // FIXME: only one screen available ? + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + final ScreenMode sm = getCurrentScreenMode(); + virtualSize.setWidth(sm.getRotatedWidth()); + virtualSize.setHeight(sm.getRotatedHeight()); + } + //---------------------------------------------------------------------- // Internals only // @@ -91,7 +105,7 @@ public class AndroidScreen extends jogamp.newt.ScreenImpl { if (ScreenMode.ROTATE_90 == nrot || ScreenMode.ROTATE_270 == nrot) { props[offset++] = outMetrics.heightPixels; props[offset++] = outMetrics.widthPixels; - } else { + } else { props[offset++] = outMetrics.widthPixels; props[offset++] = outMetrics.heightPixels; } diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java index 9cefa8163..6348cf19e 100644 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java +++ b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java @@ -239,7 +239,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { } // propagate data .. - config = eglConfig; + setGraphicsConfiguration(eglConfig); setWindowHandle(surfaceHandle); Log.d(MD.TAG, "createNativeImpl X"); } @@ -343,7 +343,9 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { surfaceHandle = 0; surface=null; } - getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event + if(getScreen().isNativeValid()) { + getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event + } if(0>x || 0>y) { x = 0; diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java index bb678935a..f7c05cd45 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java @@ -27,10 +27,7 @@ */ package jogamp.newt.driver.android; -import javax.media.opengl.GLProfile; - import com.jogamp.newt.Window; -import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; import jogamp.newt.driver.android.AndroidWindow; @@ -63,9 +60,7 @@ public class NewtBaseActivity extends Activity { } public void setContentView(android.view.Window androidWindow, Window newtWindow) { - if(newtWindow instanceof GLWindow) { - newtWindow = ((GLWindow)newtWindow).getWindow(); - } + newtWindow = newtWindow.getDelegatedWindow(); if(newtWindow instanceof AndroidWindow) { this.newtWindow = (AndroidWindow)newtWindow; this.newtWindow.setAndroidWindow(androidWindow); @@ -103,9 +98,6 @@ public class NewtBaseActivity extends Activity { jogamp.common.os.android.StaticContext.setContext(extActivity.getApplicationContext()); } extActivity.getWindow(); - - // init GLProfile - GLProfile.initSingleton(true); } @Override diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index 0729f02ab..b63e433f6 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -99,7 +99,7 @@ public class AWTCanvas extends Canvas { if(null==awtConfig) { throw new NativeWindowException("Error: NULL AWTGraphicsConfiguration"); } - chosen = awtConfig.getGraphicsConfiguration(); + chosen = awtConfig.getAWTGraphicsConfiguration(); // before native peer is valid: X11 disableBackgroundErase(); @@ -192,7 +192,7 @@ public class AWTCanvas extends Canvas { */ AWTGraphicsConfiguration config = chooseGraphicsConfiguration( awtConfig.getChosenCapabilities(), awtConfig.getRequestedCapabilities(), chooser, gc.getDevice()); - final GraphicsConfiguration compatible = (null!=config)?config.getGraphicsConfiguration():null; + final GraphicsConfiguration compatible = (null!=config)?config.getAWTGraphicsConfiguration():null; if(Window.DEBUG_IMPLEMENTATION) { Exception e = new Exception("Info: Call Stack: "+Thread.currentThread().getName()); e.printStackTrace(); @@ -246,7 +246,9 @@ public class AWTCanvas extends Canvas { CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, GraphicsDevice device) { - AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT); + final AbstractGraphicsScreen aScreen = null != device ? + AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT): + AWTGraphicsScreen.createDefault(); AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capsChosen, capsRequested, diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java index 64c741464..f22ec6fad 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,7 +34,6 @@ package jogamp.newt.driver.awt; -import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; import jogamp.newt.DisplayImpl; @@ -43,7 +43,7 @@ public class AWTDisplay extends DisplayImpl { } protected void createNativeImpl() { - aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null, AbstractGraphicsDevice.DEFAULT_UNIT); // default + aDevice = AWTGraphicsDevice.createDefault(); } protected void setAWTGraphicsDevice(AWTGraphicsDevice d) { diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java b/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java index 644c96391..9eed930b6 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTScreen.java @@ -38,6 +38,8 @@ import java.awt.DisplayMode; import jogamp.newt.ScreenImpl; import javax.media.nativewindow.awt.AWTGraphicsDevice; import javax.media.nativewindow.awt.AWTGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; public class AWTScreen extends ScreenImpl { public AWTScreen() { @@ -45,21 +47,34 @@ public class AWTScreen extends ScreenImpl { protected void createNativeImpl() { aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); - - final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); - if(null != mode) { - setScreenSize(mode.getWidth(), mode.getHeight()); - } } protected void setAWTGraphicsScreen(AWTGraphicsScreen s) { aScreen = s; } - // done by AWTWindow .. - protected void setScreenSize(int w, int h) { - super.setScreenSize(w, h); + /** + * Used by AWTWindow .. + */ + @Override + protected void updateVirtualScreenOriginAndSize() { + super.updateVirtualScreenOriginAndSize(); } protected void closeNativeImpl() { } + + protected int validateScreenIndex(int idx) { + return idx; // pass through ... + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + final DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); + if(null != mode) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(mode.getWidth()); + virtualSize.setHeight(mode.getHeight()); + } + } + } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java index 9aaa82fec..e9e3ec0ba 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java @@ -36,10 +36,11 @@ package jogamp.newt.driver.awt; import java.awt.BorderLayout; import java.awt.Container; -import java.awt.DisplayMode; import java.awt.Frame; import java.awt.Insets; + import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; import javax.media.nativewindow.awt.AWTGraphicsDevice; import javax.media.nativewindow.awt.AWTGraphicsScreen; import javax.media.nativewindow.util.Point; @@ -145,27 +146,21 @@ public class AWTWindow extends WindowImpl { public boolean hasDeviceChanged() { boolean res = canvas.hasDeviceChanged(); if(res) { - config = canvas.getAWTGraphicsConfiguration(); - if (config == null) { + final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); + if (null == cfg) { throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this); } - updateDeviceData(); + setGraphicsConfiguration(cfg); + + // propagate new info .. + ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)cfg.getScreen()); + ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)cfg.getScreen().getDevice()); + + ((AWTScreen)getScreen()).updateVirtualScreenOriginAndSize(); } return res; } - private void updateDeviceData() { - // propagate new info .. - ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)config.getScreen()); - ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)config.getScreen().getDevice()); - - final DisplayMode mode = ((AWTGraphicsDevice)config.getScreen().getDevice()).getGraphicsDevice().getDisplayMode(); - if(null != mode) { - ((AWTScreen)getScreen()).setScreenSize(mode.getWidth(), mode.getHeight()); - } - - } - protected void updateInsetsImpl(javax.media.nativewindow.util.Insets insets) { Insets contInsets = container.getInsets(); insets.setLeftWidth(contInsets.left); @@ -189,11 +184,6 @@ public class AWTWindow extends WindowImpl { container.setVisible(0 != ( FLAG_IS_VISIBLE & flags)); } - x=(x>=0)?x:AWTWindow.this.x; - y=(x>=0)?y:AWTWindow.this.y; - width=(width>0)?width:AWTWindow.this.width; - height=(height>0)?height:AWTWindow.this.height; - container.setLocation(x, y); Insets insets = container.getInsets(); container.setSize(width + insets.left + insets.right, @@ -202,11 +192,12 @@ public class AWTWindow extends WindowImpl { if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { if( 0 != ( FLAG_IS_VISIBLE & flags ) ) { if( !hasDeviceChanged() ) { - // oops ?? - config = canvas.getAWTGraphicsConfiguration(); - if(null == config) { + // oops ?? + final AWTGraphicsConfiguration cfg = canvas.getAWTGraphicsConfiguration(); + if(null == cfg) { throw new NativeWindowException("Error: !hasDeviceChanged && null == GraphicsConfiguration: "+this); } + setGraphicsConfiguration(cfg); } } visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java index 0a8453701..11b8dfcf9 100644 --- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java +++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Screen.java @@ -34,6 +34,8 @@ package jogamp.newt.driver.broadcom.egl; import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; public class Screen extends jogamp.newt.ScreenImpl { @@ -47,16 +49,26 @@ public class Screen extends jogamp.newt.ScreenImpl { protected void createNativeImpl() { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - setScreenSize(fixedWidth, fixedHeight); } protected void closeNativeImpl() { } + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(fixedWidth); // FIXME + virtualSize.setHeight(fixedHeight); // FIXME + } + //---------------------------------------------------------------------- // Internals only // - static final int fixedWidth = 1920; - static final int fixedHeight = 1080; + static final int fixedWidth = 1920; // FIXME + static final int fixedHeight = 1080; // FIXME } diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java index 7df293c0d..6f66eedd3 100644 --- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java @@ -35,6 +35,7 @@ package jogamp.newt.driver.broadcom.egl; import jogamp.opengl.egl.*; import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.AWTGraphicsConfiguration; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import javax.media.opengl.GLCapabilitiesImmutable; @@ -51,13 +52,14 @@ public class Window extends jogamp.newt.WindowImpl { if(0!=getParentWindowHandle()) { throw new RuntimeException("Window parenting not supported (yet)"); } - // query a good configuration .. even thought we drop this one - // and reuse the EGLUtil choosen one later. - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( + // query a good configuration, however chose the final one by the native queried egl-cfg-id + // after creation at {@link #windowCreated(int, int, int)}. + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); setSizeImpl(getScreen().getWidth(), getScreen().getHeight()); setWindowHandle(realizeWindow(true, width, height)); @@ -139,7 +141,7 @@ public class Window extends jogamp.newt.WindowImpl { private long realizeWindow(boolean chromaKey, int width, int height) { if(DEBUG_IMPLEMENTATION) { - System.err.println("BCEGL Window.realizeWindow() with: chroma "+chromaKey+", "+width+"x"+height+", "+config); + System.err.println("BCEGL Window.realizeWindow() with: chroma "+chromaKey+", "+width+"x"+height+", "+getGraphicsConfiguration()); } long handle = CreateWindow(getDisplayHandle(), chromaKey, width, height); if (0 == handle) { @@ -152,13 +154,14 @@ public class Window extends jogamp.newt.WindowImpl { private void windowCreated(int cfgID, int width, int height) { this.width = width; this.height = height; - GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) config.getRequestedCapabilities(); - config = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID); - if (config == null) { + GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities(); + final AbstractGraphicsConfiguration cfg = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID); + if (null == cfg) { throw new NativeWindowException("Error creating EGLGraphicsConfiguration from id: "+cfgID+", "+this); } + setGraphicsConfiguration(cfg); if(DEBUG_IMPLEMENTATION) { - System.err.println("BCEGL Window.windowCreated(): "+toHexString(cfgID)+", "+width+"x"+height+", "+config); + System.err.println("BCEGL Window.windowCreated(): "+toHexString(cfgID)+", "+width+"x"+height+", "+cfg); } } diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java index 26b7120a9..66ad1c691 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/Screen.java @@ -33,8 +33,10 @@ package jogamp.newt.driver.intel.gdl; -import jogamp.newt.*; -import javax.media.nativewindow.*; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; public class Screen extends jogamp.newt.ScreenImpl { @@ -53,6 +55,17 @@ public class Screen extends jogamp.newt.ScreenImpl { protected void closeNativeImpl() { } + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(cachedWidth); + virtualSize.setHeight(cachedHeight); + } + //---------------------------------------------------------------------- // Internals only // @@ -62,7 +75,11 @@ public class Screen extends jogamp.newt.ScreenImpl { // called by GetScreenInfo() .. private void screenCreated(int width, int height) { - setScreenSize(width, height); + cachedWidth = width; + cachedHeight = height; } + + private static int cachedWidth = 0; + private static int cachedHeight = 0; } diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java index ab3e95e7e..873d0a0c1 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java @@ -51,14 +51,15 @@ public class Window extends jogamp.newt.WindowImpl { if(0!=getParentWindowHandle()) { throw new NativeWindowException("GDL Window does not support window parenting"); } - AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice(); + final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + final AbstractGraphicsDevice aDevice = getScreen().getDisplay().getGraphicsDevice(); - config = GraphicsConfigurationFactory.getFactory(aDevice).chooseGraphicsConfiguration( + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aDevice).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen); - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); synchronized(Window.class) { setWindowHandle(nextWindowHandle++); // just a marker @@ -83,11 +84,6 @@ public class Window extends jogamp.newt.WindowImpl { protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { Screen screen = (Screen) getScreen(); - x=(x>=0)?x:this.x; - y=(x>=0)?y:this.y; - width=(width>0)?width:this.width; - height=(height>0)?height:this.height; - if(width>screen.getWidth()) { width=screen.getWidth(); } diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java b/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java index a11b08b5c..6b6aecb20 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java +++ b/src/newt/classes/jogamp/newt/driver/kd/KDScreen.java @@ -35,6 +35,8 @@ package jogamp.newt.driver.kd; import jogamp.newt.ScreenImpl; import javax.media.nativewindow.*; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; public class KDScreen extends ScreenImpl { static { @@ -50,8 +52,22 @@ public class KDScreen extends ScreenImpl { protected void closeNativeImpl() { } - // elevate access to this package .. - protected void setScreenSize(int w, int h) { - super.setScreenSize(w, h); + protected int validateScreenIndex(int idx) { + return 0; // only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(cachedWidth); + virtualSize.setHeight(cachedHeight); } + + protected void sizeChanged(int w, int h) { + cachedWidth = w; + cachedHeight = h; + } + + private static int cachedWidth = 0; + private static int cachedHeight = 0; } diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java index 10a75a017..92f8251bc 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java +++ b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java @@ -55,18 +55,19 @@ public class KDWindow extends WindowImpl { if(0!=getParentWindowHandle()) { throw new RuntimeException("Window parenting not supported (yet)"); } - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); - GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + GLCapabilitiesImmutable eglCaps = (GLCapabilitiesImmutable) cfg.getChosenCapabilities(); int[] eglAttribs = EGLGraphicsConfiguration.GLCapabilities2AttribList(eglCaps); eglWindowHandle = CreateWindow(getDisplayHandle(), eglAttribs); if (eglWindowHandle == 0) { - throw new NativeWindowException("Error creating egl window: "+config); + throw new NativeWindowException("Error creating egl window: "+cfg); } setVisible0(eglWindowHandle, false); setWindowHandle(RealizeWindow(eglWindowHandle)); @@ -145,7 +146,7 @@ public class KDWindow extends WindowImpl { @Override protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { if(fullscreen) { - ((KDScreen)getScreen()).setScreenSize(width, height); + ((KDScreen)getScreen()).sizeChanged(width, height); } super.sizeChanged(defer, newWidth, newHeight, force); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java b/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java index 527fdac6d..2ac98f255 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacDisplay.java @@ -72,8 +72,12 @@ public class MacDisplay extends DisplayImpl { public static void runNSApplication() { runNSApplication0(); } + public static void stopNSApplication() { + stopNSApplication0(); + } private static native boolean initNSApplication0(); private static native void runNSApplication0(); + private static native void stopNSApplication0(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java new file mode 100644 index 000000000..46625f7a9 --- /dev/null +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacKeyUtil.java @@ -0,0 +1,262 @@ +package jogamp.newt.driver.macosx; + +import com.jogamp.newt.event.KeyEvent; + +public class MacKeyUtil { + + // KeyCodes (independent) + private static final int kVK_Return = 0x24; + private static final int kVK_Tab = 0x30; + private static final int kVK_Space = 0x31; + private static final int kVK_Delete = 0x33; + private static final int kVK_Escape = 0x35; + private static final int kVK_Command = 0x37; + private static final int kVK_Shift = 0x38; + private static final int kVK_CapsLock = 0x39; + private static final int kVK_Option = 0x3A; + private static final int kVK_Control = 0x3B; + private static final int kVK_RightShift = 0x3C; + private static final int kVK_RightOption = 0x3D; + private static final int kVK_RightControl = 0x3E; + private static final int kVK_Function = 0x3F; + private static final int kVK_F17 = 0x40; + private static final int kVK_VolumeUp = 0x48; + private static final int kVK_VolumeDown = 0x49; + private static final int kVK_Mute = 0x4A; + private static final int kVK_F18 = 0x4F; + private static final int kVK_F19 = 0x50; + private static final int kVK_F20 = 0x5A; + private static final int kVK_F5 = 0x60; + private static final int kVK_F6 = 0x61; + private static final int kVK_F7 = 0x62; + private static final int kVK_F3 = 0x63; + private static final int kVK_F8 = 0x64; + private static final int kVK_F9 = 0x65; + private static final int kVK_F11 = 0x67; + private static final int kVK_F13 = 0x69; + private static final int kVK_F16 = 0x6A; + private static final int kVK_F14 = 0x6B; + private static final int kVK_F10 = 0x6D; + private static final int kVK_F12 = 0x6F; + private static final int kVK_F15 = 0x71; + private static final int kVK_Help = 0x72; + private static final int kVK_Home = 0x73; + private static final int kVK_PageUp = 0x74; + private static final int kVK_ForwardDelete = 0x75; + private static final int kVK_F4 = 0x76; + private static final int kVK_End = 0x77; + private static final int kVK_F2 = 0x78; + private static final int kVK_PageDown = 0x79; + private static final int kVK_F1 = 0x7A; + private static final int kVK_LeftArrow = 0x7B; + private static final int kVK_RightArrow = 0x7C; + private static final int kVK_DownArrow = 0x7D; + private static final int kVK_UpArrow = 0x7E; + + // Key constants handled differently on Mac OS X than other platforms + private static final char NSUpArrowFunctionKey = 0xF700; + private static final char NSDownArrowFunctionKey = 0xF701; + private static final char NSLeftArrowFunctionKey = 0xF702; + private static final char NSRightArrowFunctionKey = 0xF703; + private static final char NSF1FunctionKey = 0xF704; + private static final char NSF2FunctionKey = 0xF705; + private static final char NSF3FunctionKey = 0xF706; + private static final char NSF4FunctionKey = 0xF707; + private static final char NSF5FunctionKey = 0xF708; + private static final char NSF6FunctionKey = 0xF709; + private static final char NSF7FunctionKey = 0xF70A; + private static final char NSF8FunctionKey = 0xF70B; + private static final char NSF9FunctionKey = 0xF70C; + private static final char NSF10FunctionKey = 0xF70D; + private static final char NSF11FunctionKey = 0xF70E; + private static final char NSF12FunctionKey = 0xF70F; + private static final char NSF13FunctionKey = 0xF710; + private static final char NSF14FunctionKey = 0xF711; + private static final char NSF15FunctionKey = 0xF712; + private static final char NSF16FunctionKey = 0xF713; + private static final char NSF17FunctionKey = 0xF714; + private static final char NSF18FunctionKey = 0xF715; + private static final char NSF19FunctionKey = 0xF716; + private static final char NSF20FunctionKey = 0xF717; + private static final char NSF21FunctionKey = 0xF718; + private static final char NSF22FunctionKey = 0xF719; + private static final char NSF23FunctionKey = 0xF71A; + private static final char NSF24FunctionKey = 0xF71B; + private static final char NSF25FunctionKey = 0xF71C; + private static final char NSF26FunctionKey = 0xF71D; + private static final char NSF27FunctionKey = 0xF71E; + private static final char NSF28FunctionKey = 0xF71F; + private static final char NSF29FunctionKey = 0xF720; + private static final char NSF30FunctionKey = 0xF721; + private static final char NSF31FunctionKey = 0xF722; + private static final char NSF32FunctionKey = 0xF723; + private static final char NSF33FunctionKey = 0xF724; + private static final char NSF34FunctionKey = 0xF725; + private static final char NSF35FunctionKey = 0xF726; + private static final char NSInsertFunctionKey = 0xF727; + private static final char NSDeleteFunctionKey = 0xF728; + private static final char NSHomeFunctionKey = 0xF729; + private static final char NSBeginFunctionKey = 0xF72A; + private static final char NSEndFunctionKey = 0xF72B; + private static final char NSPageUpFunctionKey = 0xF72C; + private static final char NSPageDownFunctionKey = 0xF72D; + private static final char NSPrintScreenFunctionKey = 0xF72E; + private static final char NSScrollLockFunctionKey = 0xF72F; + private static final char NSPauseFunctionKey = 0xF730; + private static final char NSSysReqFunctionKey = 0xF731; + private static final char NSBreakFunctionKey = 0xF732; + private static final char NSResetFunctionKey = 0xF733; + private static final char NSStopFunctionKey = 0xF734; + private static final char NSMenuFunctionKey = 0xF735; + private static final char NSUserFunctionKey = 0xF736; + private static final char NSSystemFunctionKey = 0xF737; + private static final char NSPrintFunctionKey = 0xF738; + private static final char NSClearLineFunctionKey = 0xF739; + private static final char NSClearDisplayFunctionKey = 0xF73A; + private static final char NSInsertLineFunctionKey = 0xF73B; + private static final char NSDeleteLineFunctionKey = 0xF73C; + private static final char NSInsertCharFunctionKey = 0xF73D; + private static final char NSDeleteCharFunctionKey = 0xF73E; + private static final char NSPrevFunctionKey = 0xF73F; + private static final char NSNextFunctionKey = 0xF740; + private static final char NSSelectFunctionKey = 0xF741; + private static final char NSExecuteFunctionKey = 0xF742; + private static final char NSUndoFunctionKey = 0xF743; + private static final char NSRedoFunctionKey = 0xF744; + private static final char NSFindFunctionKey = 0xF745; + private static final char NSHelpFunctionKey = 0xF746; + private static final char NSModeSwitchFunctionKey = 0xF747; + + static int validateKeyCode(int keyCode, char keyChar) { + // OS X Virtual Keycodes + switch(keyCode) { + case kVK_Return: return KeyEvent.VK_ENTER; + case kVK_Tab: return KeyEvent.VK_TAB; + case kVK_Space: return KeyEvent.VK_SPACE; + case kVK_Delete: return KeyEvent.VK_BACK_SPACE; + case kVK_Escape: return KeyEvent.VK_ESCAPE; + case kVK_Command: return KeyEvent.VK_ALT; + case kVK_Shift: return KeyEvent.VK_SHIFT; + case kVK_CapsLock: return KeyEvent.VK_CAPS_LOCK; + case kVK_Option: return KeyEvent.VK_WINDOWS; + case kVK_Control: return KeyEvent.VK_CONTROL; + case kVK_RightShift: return KeyEvent.VK_SHIFT; + case kVK_RightOption: return KeyEvent.VK_WINDOWS; + case kVK_RightControl: return KeyEvent.VK_CONTROL; + // case kVK_Function: return KeyEvent.VK_F; + case kVK_F17: return KeyEvent.VK_F17; + // case kVK_VolumeUp: + // case kVK_VolumeDown: + // case kVK_Mute: + case kVK_F18: return KeyEvent.VK_F18; + case kVK_F19: return KeyEvent.VK_F19; + case kVK_F20: return KeyEvent.VK_F20; + case kVK_F5: return KeyEvent.VK_F5; + case kVK_F6: return KeyEvent.VK_F6; + case kVK_F7: return KeyEvent.VK_F7; + case kVK_F3: return KeyEvent.VK_F3; + case kVK_F8: return KeyEvent.VK_F8; + case kVK_F9: return KeyEvent.VK_F9; + case kVK_F11: return KeyEvent.VK_F11; + case kVK_F13: return KeyEvent.VK_F13; + case kVK_F16: return KeyEvent.VK_F16; + case kVK_F14: return KeyEvent.VK_F14; + case kVK_F10: return KeyEvent.VK_F10; + case kVK_F12: return KeyEvent.VK_F12; + case kVK_F15: return KeyEvent.VK_F15; + case kVK_Help: return KeyEvent.VK_HELP; + case kVK_Home: return KeyEvent.VK_HOME; + case kVK_PageUp: return KeyEvent.VK_PAGE_UP; + case kVK_ForwardDelete: return KeyEvent.VK_DELETE; + case kVK_F4: return KeyEvent.VK_F4; + case kVK_End: return KeyEvent.VK_END; + case kVK_F2: return KeyEvent.VK_F2; + case kVK_PageDown: return KeyEvent.VK_PAGE_DOWN; + case kVK_F1: return KeyEvent.VK_F1; + case kVK_LeftArrow: return KeyEvent.VK_LEFT; + case kVK_RightArrow: return KeyEvent.VK_RIGHT; + case kVK_DownArrow: return KeyEvent.VK_DOWN; + case kVK_UpArrow: return KeyEvent.VK_UP; + } + + if (keyChar == '\r') { + // Turn these into \n + return KeyEvent.VK_ENTER; + } + + if (keyChar >= NSUpArrowFunctionKey && keyChar <= NSModeSwitchFunctionKey) { + switch (keyChar) { + case NSUpArrowFunctionKey: return KeyEvent.VK_UP; + case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN; + case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT; + case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT; + case NSF1FunctionKey: return KeyEvent.VK_F1; + case NSF2FunctionKey: return KeyEvent.VK_F2; + case NSF3FunctionKey: return KeyEvent.VK_F3; + case NSF4FunctionKey: return KeyEvent.VK_F4; + case NSF5FunctionKey: return KeyEvent.VK_F5; + case NSF6FunctionKey: return KeyEvent.VK_F6; + case NSF7FunctionKey: return KeyEvent.VK_F7; + case NSF8FunctionKey: return KeyEvent.VK_F8; + case NSF9FunctionKey: return KeyEvent.VK_F9; + case NSF10FunctionKey: return KeyEvent.VK_F10; + case NSF11FunctionKey: return KeyEvent.VK_F11; + case NSF12FunctionKey: return KeyEvent.VK_F12; + case NSF13FunctionKey: return KeyEvent.VK_F13; + case NSF14FunctionKey: return KeyEvent.VK_F14; + case NSF15FunctionKey: return KeyEvent.VK_F15; + case NSF16FunctionKey: return KeyEvent.VK_F16; + case NSF17FunctionKey: return KeyEvent.VK_F17; + case NSF18FunctionKey: return KeyEvent.VK_F18; + case NSF19FunctionKey: return KeyEvent.VK_F19; + case NSF20FunctionKey: return KeyEvent.VK_F20; + case NSF21FunctionKey: return KeyEvent.VK_F21; + case NSF22FunctionKey: return KeyEvent.VK_F22; + case NSF23FunctionKey: return KeyEvent.VK_F23; + case NSF24FunctionKey: return KeyEvent.VK_F24; + case NSInsertFunctionKey: return KeyEvent.VK_INSERT; + case NSDeleteFunctionKey: return KeyEvent.VK_DELETE; + case NSHomeFunctionKey: return KeyEvent.VK_HOME; + case NSBeginFunctionKey: return KeyEvent.VK_BEGIN; + case NSEndFunctionKey: return KeyEvent.VK_END; + case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP; + case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN; + case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN; + case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK; + case NSPauseFunctionKey: return KeyEvent.VK_PAUSE; + // Not handled: + // NSSysReqFunctionKey + // NSBreakFunctionKey + // NSResetFunctionKey + case NSStopFunctionKey: return KeyEvent.VK_STOP; + // Not handled: + // NSMenuFunctionKey + // NSUserFunctionKey + // NSSystemFunctionKey + // NSPrintFunctionKey + // NSClearLineFunctionKey + // NSClearDisplayFunctionKey + // NSInsertLineFunctionKey + // NSDeleteLineFunctionKey + // NSInsertCharFunctionKey + // NSDeleteCharFunctionKey + // NSPrevFunctionKey + // NSNextFunctionKey + // NSSelectFunctionKey + // NSExecuteFunctionKey + // NSUndoFunctionKey + // NSRedoFunctionKey + // NSFindFunctionKey + // NSHelpFunctionKey + // NSModeSwitchFunctionKey + default: break; + } + } + + if ('a' <= keyChar && keyChar <= 'z') { + return KeyEvent.VK_A + ( keyChar - 'a' ) ; + } + + return (int) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's) + } +} diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java index 67a3f8e92..3204982be 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,9 +34,16 @@ package jogamp.newt.driver.macosx; -import com.jogamp.newt.*; +import java.util.List; + +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; + import jogamp.newt.ScreenImpl; -import javax.media.nativewindow.*; + +import com.jogamp.newt.ScreenMode; +import com.jogamp.newt.util.ScreenModeUtil; public class MacScreen extends ScreenImpl { static { @@ -47,11 +55,69 @@ public class MacScreen extends ScreenImpl { protected void createNativeImpl() { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - setScreenSize(getWidthImpl0(screen_idx), getHeightImpl0(screen_idx)); } protected void closeNativeImpl() { } private static native int getWidthImpl0(int scrn_idx); private static native int getHeightImpl0(int scrn_idx); + + private int[] getScreenModeIdx(int idx) { + int[] modeProps = getScreenMode0(screen_idx, idx); + if (null == modeProps || 0 == modeProps.length) { + return null; + } + if(modeProps.length < ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL) { + throw new RuntimeException("properties array too short, should be >= "+ScreenModeUtil.NUM_SCREEN_MODE_PROPERTIES_ALL+", is "+modeProps.length); + } + return modeProps; + } + + private int nativeModeIdx; + + protected int[] getScreenModeFirstImpl() { + nativeModeIdx = 0; + return getScreenModeNextImpl(); + } + + protected int[] getScreenModeNextImpl() { + int[] modeProps = getScreenModeIdx(nativeModeIdx); + if (null != modeProps && 0 < modeProps.length) { + nativeModeIdx++; + return modeProps; + } + return null; + } + + protected ScreenMode getCurrentScreenModeImpl() { + int[] modeProps = getScreenModeIdx(-1); + if (null != modeProps && 0 < modeProps.length) { + return ScreenModeUtil.streamIn(modeProps, 0); + } + return null; + } + + protected boolean setCurrentScreenModeImpl(final ScreenMode screenMode) { + final List<ScreenMode> screenModes = this.getScreenModesOrig(); + final int screenModeIdx = screenModes.indexOf(screenMode); + if(0>screenModeIdx) { + throw new RuntimeException("ScreenMode not element of ScreenMode list: "+screenMode); + } + final int nativeModeIdx = getScreenModesIdx2NativeIdx().get(screenModeIdx); + return setScreenMode0(screen_idx, nativeModeIdx); + } + + protected int validateScreenIndex(int idx) { + return idx; + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(getWidthImpl0(screen_idx)); + virtualSize.setHeight(getHeightImpl0(screen_idx)); + } + + private native int[] getScreenMode0(int screen_index, int mode_index); + private native boolean setScreenMode0(int screen_index, int mode_idx); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index d09ac72ba..75a3cf6d5 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -34,108 +34,24 @@ package jogamp.newt.driver.macosx; +import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.SurfaceChangeable; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import jogamp.newt.WindowImpl; +import jogamp.newt.driver.DriverClearFocus; +import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.KeyEvent; -public class MacWindow extends WindowImpl { +public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition { - // Window styles - private static final int NSBorderlessWindowMask = 0; - private static final int NSTitledWindowMask = 1 << 0; - private static final int NSClosableWindowMask = 1 << 1; - private static final int NSMiniaturizableWindowMask = 1 << 2; - private static final int NSResizableWindowMask = 1 << 3; - - // Window backing store types - private static final int NSBackingStoreRetained = 0; - private static final int NSBackingStoreNonretained = 1; - private static final int NSBackingStoreBuffered = 2; - - // Key constants handled differently on Mac OS X than other platforms - private static final int NSUpArrowFunctionKey = 0xF700; - private static final int NSDownArrowFunctionKey = 0xF701; - private static final int NSLeftArrowFunctionKey = 0xF702; - private static final int NSRightArrowFunctionKey = 0xF703; - private static final int NSF1FunctionKey = 0xF704; - private static final int NSF2FunctionKey = 0xF705; - private static final int NSF3FunctionKey = 0xF706; - private static final int NSF4FunctionKey = 0xF707; - private static final int NSF5FunctionKey = 0xF708; - private static final int NSF6FunctionKey = 0xF709; - private static final int NSF7FunctionKey = 0xF70A; - private static final int NSF8FunctionKey = 0xF70B; - private static final int NSF9FunctionKey = 0xF70C; - private static final int NSF10FunctionKey = 0xF70D; - private static final int NSF11FunctionKey = 0xF70E; - private static final int NSF12FunctionKey = 0xF70F; - private static final int NSF13FunctionKey = 0xF710; - private static final int NSF14FunctionKey = 0xF711; - private static final int NSF15FunctionKey = 0xF712; - private static final int NSF16FunctionKey = 0xF713; - private static final int NSF17FunctionKey = 0xF714; - private static final int NSF18FunctionKey = 0xF715; - private static final int NSF19FunctionKey = 0xF716; - private static final int NSF20FunctionKey = 0xF717; - private static final int NSF21FunctionKey = 0xF718; - private static final int NSF22FunctionKey = 0xF719; - private static final int NSF23FunctionKey = 0xF71A; - private static final int NSF24FunctionKey = 0xF71B; - private static final int NSF25FunctionKey = 0xF71C; - private static final int NSF26FunctionKey = 0xF71D; - private static final int NSF27FunctionKey = 0xF71E; - private static final int NSF28FunctionKey = 0xF71F; - private static final int NSF29FunctionKey = 0xF720; - private static final int NSF30FunctionKey = 0xF721; - private static final int NSF31FunctionKey = 0xF722; - private static final int NSF32FunctionKey = 0xF723; - private static final int NSF33FunctionKey = 0xF724; - private static final int NSF34FunctionKey = 0xF725; - private static final int NSF35FunctionKey = 0xF726; - private static final int NSInsertFunctionKey = 0xF727; - private static final int NSDeleteFunctionKey = 0xF728; - private static final int NSHomeFunctionKey = 0xF729; - private static final int NSBeginFunctionKey = 0xF72A; - private static final int NSEndFunctionKey = 0xF72B; - private static final int NSPageUpFunctionKey = 0xF72C; - private static final int NSPageDownFunctionKey = 0xF72D; - private static final int NSPrintScreenFunctionKey = 0xF72E; - private static final int NSScrollLockFunctionKey = 0xF72F; - private static final int NSPauseFunctionKey = 0xF730; - private static final int NSSysReqFunctionKey = 0xF731; - private static final int NSBreakFunctionKey = 0xF732; - private static final int NSResetFunctionKey = 0xF733; - private static final int NSStopFunctionKey = 0xF734; - private static final int NSMenuFunctionKey = 0xF735; - private static final int NSUserFunctionKey = 0xF736; - private static final int NSSystemFunctionKey = 0xF737; - private static final int NSPrintFunctionKey = 0xF738; - private static final int NSClearLineFunctionKey = 0xF739; - private static final int NSClearDisplayFunctionKey = 0xF73A; - private static final int NSInsertLineFunctionKey = 0xF73B; - private static final int NSDeleteLineFunctionKey = 0xF73C; - private static final int NSInsertCharFunctionKey = 0xF73D; - private static final int NSDeleteCharFunctionKey = 0xF73E; - private static final int NSPrevFunctionKey = 0xF73F; - private static final int NSNextFunctionKey = 0xF740; - private static final int NSSelectFunctionKey = 0xF741; - private static final int NSExecuteFunctionKey = 0xF742; - private static final int NSUndoFunctionKey = 0xF743; - private static final int NSRedoFunctionKey = 0xF744; - private static final int NSFindFunctionKey = 0xF745; - private static final int NSHelpFunctionKey = 0xF746; - private static final int NSModeSwitchFunctionKey = 0xF747; - - private volatile long surfaceHandle; - static { MacDisplay.initSingleton(); } @@ -143,18 +59,21 @@ public class MacWindow extends WindowImpl { public MacWindow() { } + @Override protected void createNativeImpl() { - config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen()); - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true)); if (0 == getWindowHandle()) { throw new NativeWindowException("Error creating window"); } } + @Override protected void closeNativeImpl() { try { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } @@ -168,81 +87,158 @@ public class MacWindow extends WindowImpl { } } finally { setWindowHandle(0); + surfaceHandle = 0; + sscSurfaceHandle = 0; + isOffscreenInstance = false; } } @Override protected int lockSurfaceImpl() { - return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; + if(!isOffscreenInstance) { + return lockSurface0(getWindowHandle()) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY; + } + return LOCK_SUCCESS; } @Override protected void unlockSurfaceImpl() { - unlockSurface0(getWindowHandle()); + if(!isOffscreenInstance) { + unlockSurface0(getWindowHandle()); + } } @Override public final long getSurfaceHandle() { - return surfaceHandle; + return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; + } + + public void setSurfaceHandle(long surfaceHandle) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); + } + sscSurfaceHandle = surfaceHandle; + if (isNativeValid()) { + if (0 != sscSurfaceHandle) { + orderOut0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } /** this is done by recreation! + else if (isVisible()){ + orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() ); + } */ + } } + public void surfaceSizeChanged(int width, int height) { + sizeChanged(false, width, height, false); + } + @Override protected void setTitleImpl(final String title) { setTitle0(getWindowHandle(), title); } protected void requestFocusImpl(boolean force) { - requestFocus0(getWindowHandle(), force); + if(!isOffscreenInstance) { + requestFocus0(getWindowHandle(), force); + } else { + focusChanged(false, true); + } + } + + public final void clearFocus() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); + } + if(!isOffscreenInstance) { + requestFocusParent0(getWindowHandle()); + } else { + focusChanged(false, false); + } + } + + public void updatePosition() { + final Point pS = getTopLevelLocationOnScreen(getX(), getY()); + if(DEBUG_IMPLEMENTATION) { + System.err.println("MacWindow: updatePosition() - isOffscreenInstance "+isOffscreenInstance+", new abs pos: pS "+pS); + } + if( !isOffscreenInstance ) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); + } // else no offscreen position + // no native event (fullscreen, some reparenting) + super.positionChanged(true, getX(), getY()); } + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - final PointImmutable pS = position2TopLevel(new Point(x, y)); + final Point pS = getTopLevelLocationOnScreen(x, y); + isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+", "+ - getReconfigureFlagsAsString(null, flags)); + System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ + ", offscreenInstance "+isOffscreenInstance+ + ", "+getReconfigureFlagsAsString(null, flags)); } - if( getWindowHandle() == 0 ) { - if( 0 != ( FLAG_IS_VISIBLE & flags) ) { - createWindow(false, pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - // no native event .. - visibleChanged(true, true); - } /* else { ?? } */ - } else { - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { + if ( !isOffscreenInstance ) { orderOut0(getWindowHandle()); - // no native event .. - visibleChanged(true, false); - } - if( 0 != ( FLAG_CHANGE_DECORATION & flags) || - 0 != ( FLAG_CHANGE_PARENTING & flags) || - 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(true, pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } - } - if(x>=0 && y>=0) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); - // no native event (fullscreen, some reparenting) - positionChanged(true, getLocationOnScreenImpl(0, 0)); // incl. validation } - if(width>0 && height>0) { + // no native event .. + visibleChanged(true, false); + } + if( 0 == getWindowHandle() && 0 != ( FLAG_IS_VISIBLE & flags) || + 0 != ( FLAG_CHANGE_DECORATION & flags) || + 0 != ( FLAG_CHANGE_PARENTING & flags) || + 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { + createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } + } + if(x>=0 && y>=0) { + if( !isOffscreenInstance ) { + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), pS.getX(), pS.getY()); + } // else no offscreen position + // no native event (fullscreen, some reparenting) + super.positionChanged(true, x, y); + } + if(width>0 && height>0) { + if( !isOffscreenInstance ) { setContentSize0(getWindowHandle(), width, height); - // no native event (fullscreen, some reparenting) - sizeChanged(true, width, height, false); // incl. validation (incl. repositioning) - } - if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { + } // else offscreen size is realized via recreation + // no native event (fullscreen, some reparenting) + sizeChanged(true, width, height, false); // incl. validation (incl. repositioning) + } + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { + if( !isOffscreenInstance ) { orderFront0(getWindowHandle()); - // no native event .. - visibleChanged(true, true); - } + } + // no native event .. + visibleChanged(true, true); + } + if( !isOffscreenInstance ) { setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags)); } return true; } protected Point getLocationOnScreenImpl(int x, int y) { - return (Point) getLocationOnScreen0(getWindowHandle(), x, y); + Point p = new Point(x, y); + // min val is 0 + p.setX(Math.max(p.getX(), 0)); + p.setY(Math.max(p.getY(), 0)); + + final NativeWindow parent = getParent(); + if( null != parent && 0 != parent.getWindowHandle() ) { + p.translate(parent.getLocationOnScreen(null)); + } + return p; + } + + private Point getTopLevelLocationOnScreen(int x, int y) { + final InsetsImmutable _insets = getInsets(); // zero if undecorated + // client position -> top-level window position + x -= _insets.getLeftWidth() ; + y -= _insets.getTopHeight() ; + return getLocationOnScreenImpl(x, y); } protected void updateInsetsImpl(Insets insets) { @@ -252,138 +248,76 @@ public class MacWindow extends WindowImpl { @Override protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { if(width != newWidth || height != newHeight) { - final Point p0S = position2TopLevel(new Point(x, y)); + final Point p0S = getTopLevelLocationOnScreen(x, y); setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); } super.sizeChanged(defer, newWidth, newHeight, force); } @Override - protected void positionChanged(boolean defer, int newX, int newY) { - positionChanged(defer, new Point(newX, newY)); + protected void positionChanged(boolean defer, int newX, int newY) { + // passed coordinates are in screen position of the client area + if(getWindowHandle()!=0) { + // screen position -> window position + Point absPos = new Point(newX, newY); + final NativeWindow parent = getParent(); + if(null != parent) { + absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); + } + super.positionChanged(defer, absPos.getX(), absPos.getY()); + } } @Override protected boolean setPointerVisibleImpl(final boolean pointerVisible) { - return setPointerVisible0(getWindowHandle(), pointerVisible); + if( !isOffscreenInstance ) { + return setPointerVisible0(getWindowHandle(), pointerVisible); + } // else may need offscreen solution ? FIXME + return false; } @Override protected boolean confinePointerImpl(final boolean confine) { - return confinePointer0(getWindowHandle(), confine); + if( !isOffscreenInstance ) { + return confinePointer0(getWindowHandle(), confine); + } // else may need offscreen solution ? FIXME + return false; } @Override protected void warpPointerImpl(final int x, final int y) { - warpPointer0(getWindowHandle(), x, y); + if( !isOffscreenInstance ) { + warpPointer0(getWindowHandle(), x, y); + } // else may need offscreen solution ? FIXME } @Override public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { - final int key = convertKeyChar(keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()); // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system - super.sendKeyEvent(eventType, modifiers, key, keyChar); + final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); } @Override public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { - final int key = convertKeyChar(keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()); // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system - super.enqueueKeyEvent(wait, eventType, modifiers, key, keyChar); + final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); } //---------------------------------------------------------------------- // Internals only // - private char convertKeyChar(char keyChar) { - if (keyChar == '\r') { - // Turn these into \n - return '\n'; - } - - if (keyChar >= NSUpArrowFunctionKey && keyChar <= NSModeSwitchFunctionKey) { - switch (keyChar) { - case NSUpArrowFunctionKey: return KeyEvent.VK_UP; - case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN; - case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT; - case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT; - case NSF1FunctionKey: return KeyEvent.VK_F1; - case NSF2FunctionKey: return KeyEvent.VK_F2; - case NSF3FunctionKey: return KeyEvent.VK_F3; - case NSF4FunctionKey: return KeyEvent.VK_F4; - case NSF5FunctionKey: return KeyEvent.VK_F5; - case NSF6FunctionKey: return KeyEvent.VK_F6; - case NSF7FunctionKey: return KeyEvent.VK_F7; - case NSF8FunctionKey: return KeyEvent.VK_F8; - case NSF9FunctionKey: return KeyEvent.VK_F9; - case NSF10FunctionKey: return KeyEvent.VK_F10; - case NSF11FunctionKey: return KeyEvent.VK_F11; - case NSF12FunctionKey: return KeyEvent.VK_F12; - case NSF13FunctionKey: return KeyEvent.VK_F13; - case NSF14FunctionKey: return KeyEvent.VK_F14; - case NSF15FunctionKey: return KeyEvent.VK_F15; - case NSF16FunctionKey: return KeyEvent.VK_F16; - case NSF17FunctionKey: return KeyEvent.VK_F17; - case NSF18FunctionKey: return KeyEvent.VK_F18; - case NSF19FunctionKey: return KeyEvent.VK_F19; - case NSF20FunctionKey: return KeyEvent.VK_F20; - case NSF21FunctionKey: return KeyEvent.VK_F21; - case NSF22FunctionKey: return KeyEvent.VK_F22; - case NSF23FunctionKey: return KeyEvent.VK_F23; - case NSF24FunctionKey: return KeyEvent.VK_F24; - case NSInsertFunctionKey: return KeyEvent.VK_INSERT; - case NSDeleteFunctionKey: return KeyEvent.VK_DELETE; - case NSHomeFunctionKey: return KeyEvent.VK_HOME; - case NSBeginFunctionKey: return KeyEvent.VK_BEGIN; - case NSEndFunctionKey: return KeyEvent.VK_END; - case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP; - case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN; - case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN; - case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK; - case NSPauseFunctionKey: return KeyEvent.VK_PAUSE; - // Not handled: - // NSSysReqFunctionKey - // NSBreakFunctionKey - // NSResetFunctionKey - case NSStopFunctionKey: return KeyEvent.VK_STOP; - // Not handled: - // NSMenuFunctionKey - // NSUserFunctionKey - // NSSystemFunctionKey - // NSPrintFunctionKey - // NSClearLineFunctionKey - // NSClearDisplayFunctionKey - // NSInsertLineFunctionKey - // NSDeleteLineFunctionKey - // NSInsertCharFunctionKey - // NSDeleteCharFunctionKey - // NSPrevFunctionKey - // NSNextFunctionKey - // NSSelectFunctionKey - // NSExecuteFunctionKey - // NSUndoFunctionKey - // NSRedoFunctionKey - // NSFindFunctionKey - // NSHelpFunctionKey - // NSModeSwitchFunctionKey - default: break; - } - } - - // NSEvent's charactersIgnoringModifiers doesn't ignore the shift key - if (keyChar >= 'a' && keyChar <= 'z') { - return Character.toUpperCase(keyChar); - } - - return keyChar; - } - - private void createWindow(final boolean recreate, + private void createWindow(final boolean offscreenInstance, final boolean recreate, final PointImmutable pS, final int width, final int height, final boolean fullscreen) { @@ -406,59 +340,27 @@ public class MacWindow extends WindowImpl { } setWindowHandle(createWindow0(getParentWindowHandle(), pS.getX(), pS.getY(), width, height, - config.getChosenCapabilities().isBackgroundOpaque(), + (getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance), fullscreen, - (isUndecorated() ? - NSBorderlessWindowMask : - NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), + ((isUndecorated() || offscreenInstance) ? + NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), NSBackingStoreBuffered, getScreen().getIndex(), surfaceHandle)); if (getWindowHandle() == 0) { throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); } surfaceHandle = contentView0(getWindowHandle()); - setTitle0(getWindowHandle(), getTitle()); - // need to revalidate real position - positionChanged(true, getLocationOnScreenImpl(0, 0)); // incl. validation + if( offscreenInstance ) { + orderOut0(0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle()); + } else { + setTitle0(getWindowHandle(), getTitle()); + } } catch (Exception ie) { ie.printStackTrace(); } } - private void positionChanged(boolean defer, Point absPos) { - if(getWindowHandle()!=0) { - position2ClientSpace(absPos); - super.positionChanged(defer, absPos.getX(), absPos.getY()); - } - } - - private Point position2ClientSpace(Point absPos) { - final NativeWindow parent = getParent(); - if(null != parent) { - return absPos.translate( parent.getLocationOnScreen(null).scale(-1, -1) ); - } - return absPos; - } - - private Point position2TopLevel(Point clientPos) { - if(0<=clientPos.getX() && 0<=clientPos.getY()) { - final InsetsImmutable _insets = getInsets(); // zero if undecorated - // client position -> top-level window position - clientPos.setX(clientPos.getX() - _insets.getLeftWidth()) ; - clientPos.setY(clientPos.getY() - _insets.getTopHeight()) ; - } - // min val is 0 - clientPos.setX(Math.max(clientPos.getX(), 0)); - clientPos.setY(Math.max(clientPos.getY(), 0)); - // On MacOSX the absolute position is required to position - // a window - even a child window! - final NativeWindow parent = getParent(); - if( null != parent && 0 != parent.getWindowHandle() ) { - clientPos.translate(parent.getLocationOnScreen(null)); - } - return clientPos; - } - protected static native boolean initIDs0(); private native long createWindow0(long parentWindowHandle, int x, int y, int w, int h, boolean opaque, boolean fullscreen, int windowStyle, @@ -467,6 +369,7 @@ public class MacWindow extends WindowImpl { private native boolean lockSurface0(long window); private native void unlockSurface0(long window); private native void requestFocus0(long window, boolean force); + private native void requestFocusParent0(long window); /** in case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); private native void orderFront0(long window); @@ -481,4 +384,21 @@ public class MacWindow extends WindowImpl { private static native boolean setPointerVisible0(long windowHandle, boolean visible); private static native boolean confinePointer0(long windowHandle, boolean confine); private static native void warpPointer0(long windowHandle, int x, int y); + + // Window styles + private static final int NSBorderlessWindowMask = 0; + private static final int NSTitledWindowMask = 1 << 0; + private static final int NSClosableWindowMask = 1 << 1; + private static final int NSMiniaturizableWindowMask = 1 << 2; + private static final int NSResizableWindowMask = 1 << 3; + + // Window backing store types + private static final int NSBackingStoreRetained = 0; + private static final int NSBackingStoreNonretained = 1; + private static final int NSBackingStoreBuffered = 2; + + private volatile long surfaceHandle = 0; + private long sscSurfaceHandle = 0; + private boolean isOffscreenInstance = false; + } diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java index f2e457a0f..f8bce9da3 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsScreen.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,17 +33,15 @@ */ package jogamp.newt.driver.windows; -import com.jogamp.common.util.ArrayHashSet; -import java.util.ArrayList; +import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; -import com.jogamp.newt.*; import jogamp.newt.ScreenImpl; + import com.jogamp.newt.ScreenMode; -import jogamp.newt.ScreenModeStatus; import com.jogamp.newt.util.ScreenModeUtil; -import javax.media.nativewindow.*; - public class WindowsScreen extends ScreenImpl { static { @@ -54,9 +53,8 @@ public class WindowsScreen extends ScreenImpl { protected void createNativeImpl() { aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx); - setScreenSize(getWidthImpl0(screen_idx), getHeightImpl0(screen_idx)); } - + protected void closeNativeImpl() { } @@ -104,9 +102,21 @@ public class WindowsScreen extends ScreenImpl { sm.getRotation()); } + protected int validateScreenIndex(int idx) { + return 0; // big-desktop, only one screen available + } + + protected void getVirtualScreenOriginAndSize(Point virtualOrigin, Dimension virtualSize) { + virtualOrigin.setX(getOriginX0(screen_idx)); + virtualOrigin.setY(getOriginY0(screen_idx)); + virtualSize.setWidth(getWidthImpl0(screen_idx)); + virtualSize.setHeight(getHeightImpl0(screen_idx)); + } + // Native calls + private native int getOriginX0(int screen_idx); + private native int getOriginY0(int screen_idx); private native int getWidthImpl0(int scrn_idx); - private native int getHeightImpl0(int scrn_idx); private native int[] getScreenMode0(int screen_index, int mode_index); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index cd5909d42..ff3bd5ef6 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -35,13 +35,17 @@ package jogamp.newt.driver.windows; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIUtil; import jogamp.newt.WindowImpl; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; +import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; @@ -100,17 +104,18 @@ public class WindowsWindow extends WindowImpl { } protected void createNativeImpl() { - WindowsScreen screen = (WindowsScreen) getScreen(); - WindowsDisplay display = (WindowsDisplay) screen.getDisplay(); - config = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration( + final WindowsScreen screen = (WindowsScreen) getScreen(); + final WindowsDisplay display = (WindowsDisplay) screen.getDisplay(); + final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen()); - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } + setGraphicsConfiguration(cfg); final int flags = getReconfigureFlags(0, true) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(), - getParentWindowHandle(), x, y, width, height, flags)); + getParentWindowHandle(), x, y, width, height, autoPosition, flags)); if (getWindowHandle() == 0) { throw new NativeWindowException("Error creating window"); } @@ -169,12 +174,8 @@ public class WindowsWindow extends WindowImpl { final InsetsImmutable i = getInsets(); // client position -> top-level window position - if(0<=x && 0<=y) { - x -= i.getLeftWidth() ; - y -= i.getTopHeight() ; - if( 0 > x ) { x = 0; } - if( 0 > y ) { y = 0; } - } + x -= i.getLeftWidth() ; + y -= i.getTopHeight() ; if(0<width && 0<height) { // client size -> top-level window size @@ -237,13 +238,43 @@ public class WindowsWindow extends WindowImpl { } protected Point getLocationOnScreenImpl(int x, int y) { - return GDI.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y); + return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y); } protected void updateInsetsImpl(Insets insets) { // nop - using event driven insetsChange(..) } + private final int validateKeyCode(int eventType, int keyCode) { + switch(eventType) { + case KeyEvent.EVENT_KEY_PRESSED: + lastPressedKeyCode = keyCode; + break; + case KeyEvent.EVENT_KEY_TYPED: + if(-1==keyCode) { + keyCode = lastPressedKeyCode; + } + lastPressedKeyCode = -1; + break; + } + return keyCode; + } + private int lastPressedKeyCode = 0; + + @Override + public void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform + keyCode = validateKeyCode(eventType, keyCode); + super.sendKeyEvent(eventType, modifiers, keyCode, keyChar); + } + + @Override + public void enqueueKeyEvent(boolean wait, int eventType, int modifiers, int keyCode, char keyChar) { + // Note that we have to regenerate the keyCode for EVENT_KEY_TYPED on this platform + keyCode = validateKeyCode(eventType, keyCode); + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keyChar); + } + //---------------------------------------------------------------------- // Internals only // @@ -252,7 +283,7 @@ public class WindowsWindow extends WindowImpl { private native long CreateWindow0(long hInstance, String wndClassName, String wndName, long parentWindowHandle, - int x, int y, int width, int height, int flags); + int x, int y, int width, int height, boolean autoPosition, int flags); private native long MonitorFromWindow0(long windowHandle); private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, int flags); diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java b/src/newt/classes/jogamp/newt/driver/x11/X11Display.java index b9a32c7de..b3bc6e475 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Display.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11Display.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,10 +34,14 @@ package jogamp.newt.driver.x11; -import javax.media.nativewindow.*; -import javax.media.nativewindow.x11.*; -import jogamp.newt.*; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.x11.X11GraphicsDevice; + import jogamp.nativewindow.x11.X11Util; +import jogamp.newt.DisplayImpl; +import jogamp.newt.NEWTJNILibLoader; public class X11Display extends DisplayImpl { @@ -64,6 +69,20 @@ public class X11Display extends DisplayImpl { return X11Util.validateDisplayName(name, handle); } + /** + * {@inheritDoc} + * + * We use a private non-shared X11 Display instance for EDT window operations and one for exposed animation, eg. OpenGL. + * <p> + * In case {@link X11Util#HAS_XLOCKDISPLAY_BUG} and {@link X11Util#XINITTHREADS_ALWAYS_ENABLED}, + * we use null locking. Even though this seems not to be rational, it gives most stable results on all platforms. + * </p> + * <p> + * Otherwise we use basic locking via the constructor {@link X11GraphicsDevice#X11GraphicsDevice(long, int, boolean)}, + * since it is possible to share this device via {@link com.jogamp.newt.NewtFactory#createDisplay(String, boolean)}. + * </p> + */ + @SuppressWarnings("unused") protected void createNativeImpl() { long handle = X11Util.openDisplay(name); if( 0 == handle ) { @@ -85,12 +104,11 @@ public class X11Display extends DisplayImpl { throw e; } - if(X11Util.XINITTHREADS_ALWAYS_ENABLED) { - // Hack: Force non X11Display locking, even w/ AWT and w/o isFirstUIActionOnProcess() - aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock()); + // see API doc above! + if(X11Util.XINITTHREADS_ALWAYS_ENABLED && X11Util.HAS_XLOCKDISPLAY_BUG) { + aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), false); } else { - // Proper: Use AWT/X11Display locking w/ AWT and X11Display locking only w/o isFirstUIActionOnProcess() - aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT); + aDevice = new X11GraphicsDevice(handle, AbstractGraphicsDevice.DEFAULT_UNIT, false); } } diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java index 5c9c326d7..ed5ebc04e 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11Screen.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -32,6 +33,8 @@ */ package jogamp.newt.driver.x11; +import jogamp.nativewindow.x11.X11Lib; +import jogamp.nativewindow.x11.X11Util; import jogamp.newt.DisplayImpl; import jogamp.newt.ScreenImpl; import jogamp.newt.DisplayImpl.DisplayRunnable; @@ -40,6 +43,8 @@ import com.jogamp.newt.ScreenMode; import com.jogamp.newt.util.ScreenModeUtil; import java.util.List; +import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.Point; import javax.media.nativewindow.x11.*; public class X11Screen extends ScreenImpl { @@ -55,11 +60,7 @@ public class X11Screen extends ScreenImpl { // validate screen index Long handle = display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Long>() { public Long run(long dpy) { - long handle = GetScreen0(dpy, screen_idx); - if(0 != handle) { - setScreenSize(getWidth0(dpy, screen_idx), getHeight0(dpy, screen_idx)); - } - return new Long(handle); + return new Long(GetScreen0(dpy, screen_idx)); } } ); if (handle.longValue() == 0) { throw new RuntimeException("Error creating screen: " + screen_idx); @@ -245,35 +246,64 @@ public class X11Screen extends ScreenImpl { } }).booleanValue(); - if(DEBUG && done) { + if(DEBUG || !done) { System.err.println("X11Screen.setCurrentScreenModeImpl: TO ("+SCREEN_MODE_CHANGE_TIMEOUT+") reached: "+ - (System.currentTimeMillis()-t0)+"ms"); + (System.currentTimeMillis()-t0)+"ms; Current: "+getCurrentScreenMode()+"; Desired: "+screenMode); } return done; } + private class XineramaEnabledQuery implements DisplayImpl.DisplayRunnable<Boolean> { + public Boolean run(long dpy) { + return new Boolean(X11Lib.XineramaEnabled(dpy)); + } + } + private XineramaEnabledQuery xineramaEnabledQuery = new XineramaEnabledQuery(); + + protected int validateScreenIndex(final int idx) { + if(getDisplay().isNativeValid()) { + return runWithLockedDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; + } else { + return runWithTempDisplayHandle( xineramaEnabledQuery ).booleanValue() ? 0 : idx; + } + } + + protected void getVirtualScreenOriginAndSize(final Point virtualOrigin, final Dimension virtualSize) { + display.runWithLockedDisplayHandle( new DisplayImpl.DisplayRunnable<Object>() { + public Object run(long dpy) { + virtualOrigin.setX(0); + virtualOrigin.setY(0); + virtualSize.setWidth(getWidth0(dpy, screen_idx)); + virtualSize.setHeight(getHeight0(dpy, screen_idx)); + return null; + } } ); + } + //---------------------------------------------------------------------- // Internals only // private final <T> T runWithLockedDisplayHandle(DisplayRunnable<T> action) { return display.runWithLockedDisplayHandle(action); // return runWithTempDisplayHandle(action); + // return runWithoutLock(action); } - /** just here for testing some X11 RANDR bugs .. etc .. - private final Object runWithTempDisplayHandle(DisplayRunnable action) { - long dpy = X11Util.openDisplay(null); - if(0 == dpy) { + private final <T> T runWithTempDisplayHandle(DisplayRunnable<T> action) { + final long displayHandle = X11Util.openDisplay(display.getName()); + if(0 == displayHandle) { throw new RuntimeException("null device"); } - Object res; + T res; try { - res = action.run(dpy); + res = action.run(displayHandle); } finally { - X11Util.closeDisplay(dpy); + X11Util.closeDisplay(displayHandle); } return res; - } */ + } + private final <T> T runWithoutLock(DisplayRunnable<T> action) { + return action.run(display.getHandle()); + } private static native long GetScreen0(long dpy, int scrn_idx); diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java index 2b6bac215..33b541c34 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -33,7 +34,7 @@ package jogamp.newt.driver.x11; -import jogamp.nativewindow.x11.X11Util; +import jogamp.nativewindow.x11.X11Lib; import jogamp.newt.DisplayImpl; import jogamp.newt.DisplayImpl.DisplayRunnable; import jogamp.newt.WindowImpl; @@ -43,9 +44,15 @@ import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; +import com.jogamp.newt.event.MouseEvent; + public class X11Window extends WindowImpl { private static final String WINDOW_CLASS_NAME = "NewtWindow"; - + private static final int X11_WHEEL_ONE_UP_BUTTON = 4; + private static final int X11_WHEEL_ONE_DOWN_BUTTON = 5; + private static final int X11_WHEEL_TWO_UP_BUTTON = 6; + private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7; + static { X11Display.initSingleton(); } @@ -57,22 +64,22 @@ public class X11Window extends WindowImpl { final X11Screen screen = (X11Screen) getScreen(); final X11Display display = (X11Display) screen.getDisplay(); final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(display.getGraphicsDevice()); - config = factory.chooseGraphicsConfiguration( + final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) factory.chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, screen.getGraphicsScreen()); if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+config); + System.err.println("X11Window.createNativeImpl() factory: "+factory+", chosen config: "+cfg); } - if (config == null) { + if (null == cfg) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } - X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; - final long visualID = x11config.getVisualID(); + setGraphicsConfiguration(cfg); + final long visualID = cfg.getVisualID(); final int flags = getReconfigureFlags(0, true) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; setWindowHandle(CreateWindow0(getParentWindowHandle(), display.getEDTHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, flags)); + x, y, width, height, autoPosition, flags)); windowHandleClose = getWindowHandle(); if (0 == windowHandleClose) { throw new NativeWindowException("Error creating window"); @@ -101,14 +108,12 @@ public class X11Window extends WindowImpl { System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ getReconfigureFlagsAsString(null, flags)); } - if(0 == ( FLAG_IS_UNDECORATED & flags) && 0<=x && 0<=y) { + if(0 == ( FLAG_IS_UNDECORATED & flags)) { final InsetsImmutable i = getInsets(); // client position -> top-level window position x -= i.getLeftWidth() ; y -= i.getTopHeight() ; - if( 0 > x ) { x = 0; } - if( 0 > y ) { y = 0; } } reconfigureWindow0( getDisplayEDTHandle(), getScreenIndex(), getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags); @@ -167,13 +172,55 @@ public class X11Window extends WindowImpl { protected Point getLocationOnScreenImpl(final int x, final int y) { // X11Util.GetRelativeLocation: locks display already ! - return X11Util.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); + return X11Lib.GetRelativeLocation( getScreen().getDisplay().getHandle(), getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y); } protected void updateInsetsImpl(Insets insets) { // nop - using event driven insetsChange(..) } + protected void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, + int x, int y, int button, int rotation) { + switch(eventType) { + case MouseEvent.EVENT_MOUSE_PRESSED: + switch(button) { + case X11_WHEEL_ONE_UP_BUTTON: + case X11_WHEEL_ONE_DOWN_BUTTON: + case X11_WHEEL_TWO_UP_BUTTON: + case X11_WHEEL_TWO_DOWN_BUTTON: + // ignore wheel pressed ! + return; + } + break; + case MouseEvent.EVENT_MOUSE_RELEASED: + switch(button) { + case X11_WHEEL_ONE_UP_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 1; + rotation = 1; + break; + case X11_WHEEL_ONE_DOWN_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 1; + rotation = -1; + break; + case X11_WHEEL_TWO_UP_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 2; + rotation = 1; + break; + case X11_WHEEL_TWO_DOWN_BUTTON: + eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED; + button = 2; + rotation = -1; + break; + } + break; + } + super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotation); + } + + //---------------------------------------------------------------------- // Internals only // @@ -190,7 +237,7 @@ public class X11Window extends WindowImpl { private native long CreateWindow0(long parentWindowHandle, long display, int screen_index, long visualID, long javaObjectAtom, long windowDeleteAtom, - int x, int y, int width, int height, int flags); + int x, int y, int width, int height, boolean autoPosition, int flags); private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom); private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle, int x, int y, int width, int height, int flags); diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 5f1affed1..e6bc7952e 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -256,7 +256,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_kd_KDWindow_RealizeWindow jint res = kdRealizeWindow(w, &nativeWindow); if(res) { fprintf(stderr, "[RealizeWindow] failed: 0x%X, 0x%X\n", res, kdGetError()); - nativeWindow = NULL; + nativeWindow = 0; } DBG_PRINT( "[RealizeWindow] ok: %p\n", nativeWindow); return (jlong) (intptr_t) nativeWindow; diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h index 1ead0f5e8..0f7b1606b 100644 --- a/src/newt/native/KeyEvent.h +++ b/src/newt/native/KeyEvent.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef _KEY_EVENT_H_ #define _KEY_EVENT_H_ diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index a13ffaf31..ddd59f0a1 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -38,6 +38,7 @@ #import "MouseEvent.h" #import "KeyEvent.h" +#import "ScreenMode.h" #import <ApplicationServices/ApplicationServices.h> @@ -48,7 +49,6 @@ static const char * const ClazzAnyCstrName = "<init>"; static const char * const ClazzNamePointCstrSignature = "(II)V"; static jclass pointClz = NULL; static jmethodID pointCstr = NULL; -static jmethodID focusActionID = NULL; static NSString* jstringToNSString(JNIEnv* env, jstring jstr) { @@ -192,13 +192,57 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_initNSAppli JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_runNSApplication0 (JNIEnv *env, jclass clazz) { - // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "\nrunNSApplication0.0\n"); [NSApp run]; DBG_PRINT( "\nrunNSApplication0.X\n"); - // [pool release]; + [pool release]; +} + +/* + * Class: jogamp_newt_driver_macosx_MacDisplay + * Method: stopNSApplication0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacDisplay_stopNSApplication0 + (JNIEnv *env, jclass clazz) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + DBG_PRINT( "\nstopNSApplication0.0 nsApp.running %d\n", (NSApp && [NSApp isRunning])); + + if(NSApp && [NSApp isRunning]) { + [NSApp performSelectorOnMainThread:@selector(stop:) withObject:nil waitUntilDone:YES]; + // [NSApp stop: nil]; + NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: 0.0 + windowNumber: 0 + context: nil + subtype: 0 + data1: 0 + data2: 0]; + DBG_PRINT( "\nstopNSApplication0.1\n"); + [NSApp postEvent: event atStart: true]; + } + /** + DBG_PRINT( "\nstopNSApplication0.2\n"); + if(NSApp && [NSApp isRunning]) { + DBG_PRINT( "\nstopNSApplication0.3\n"); + [NSApp terminate:nil]; + } */ + + DBG_PRINT( "\nstopNSApplication0.X\n"); + [pool release]; +} + +static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + return (NSScreen *) [screens objectAtIndex: screen_idx]; } /* @@ -211,10 +255,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getWidthImpl0 { 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]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); NSRect rect = [screen frame]; [pool release]; @@ -232,10 +273,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0 { 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]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)screen_idx); NSRect rect = [screen frame]; [pool release]; @@ -243,6 +281,175 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getHeightImpl0 return (jint) (rect.size.height); } +static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { + // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + NSDictionary * dict = [screen deviceDescription]; + NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; + // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size + return (CGDirectDisplayID) [val integerValue]; +} + +/** + * Only in >= 10.6: + * CGDisplayModeGetWidth(mode) + * CGDisplayModeGetRefreshRate(mode) + * CGDisplayModeGetHeight(mode) + */ +static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) +{ + long value = 0; + CFNumberRef numRef; + numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); + if (numRef != NULL) + CFNumberGetValue(numRef, kCFNumberLongType, &value); + return value; +} +#define CGDDGetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth) +#define CGDDGetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight) +#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) +#define CGDDGetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel) + +// Duplicate each Mode by all possible rotations (4): +// For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270] +#define ROTMODES_PER_REALMODE 4 + +/* + * Class: jogamp_newt_driver_macosx_MacScreen + * Method: getScreenMode0 + * Signature: (II)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0 + (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + int prop_num = NUM_SCREEN_MODE_PROPERTIES_ALL; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + + CFArrayRef availableModes = CGDisplayAvailableModes(display); + CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); + CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; + CFDictionaryRef mode = NULL; + int currentCCWRot = (int)CGDisplayRotation(display); + jint ccwRot = 0; + +#ifdef VERBOSE_ON + if(0 >= mode_idx) { + // only for current mode (-1) and first mode (scanning) + DBG_PRINT( "getScreenMode0: scrn %d (%p, %p), mode %d, avail: %d/%d, current rot %d ccw\n", + (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); + } +#endif + + if(numberOfAvailableModesRots<=mode_idx) { + // n/a - end of modes + DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n", + (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + [pool release]; + return (*env)->NewIntArray(env, 0); + } else if(-1 < mode_idx) { + // only at initialization time, where index >= 0 + prop_num++; // add 1st extra prop, mode_idx + mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); + ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; + } else { + // current mode + mode = CGDisplayCurrentMode(display); + ccwRot = currentCCWRot; + } + // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef + + CGSize screenDim = CGDisplayScreenSize(display); + int mWidth = CGDDGetModeWidth(mode); + int mHeight = CGDDGetModeHeight(mode); + + // swap width and height, since OSX reflects rotated dimension, we don't + if ( 90 == currentCCWRot || 270 == currentCCWRot ) { + int tempWidth = mWidth; + mWidth = mHeight; + mHeight = tempWidth; + } + + jint prop[ prop_num ]; + int propIndex = 0; + int propIndexRes = 0; + + if( -1 < mode_idx ) { + prop[propIndex++] = mode_idx; + } + prop[propIndex++] = 0; // set later for verification of iterator + propIndexRes = propIndex; + prop[propIndex++] = mWidth; + prop[propIndex++] = mHeight; + prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); + prop[propIndex++] = (jint) screenDim.width; + prop[propIndex++] = (jint) screenDim.height; + prop[propIndex++] = CGDDGetModeRefreshRate(mode); + prop[propIndex++] = ccwRot; + prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL + + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n", + (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, + (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], + (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]); + + jintArray properties = (*env)->NewIntArray(env, prop_num); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", prop_num); + } + (*env)->SetIntArrayRegion(env, properties, 0, prop_num, prop); + + // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef + [pool release]; + + return properties; +} + +/* + * Class: jogamp_newt_driver_macosx_MacScreen + * Method: setScreenMode0 + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMode0 + (JNIEnv *env, jobject object, jint scrn_idx, jint mode_idx) +{ + jboolean res = JNI_TRUE; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + + CFArrayRef availableModes = CGDisplayAvailableModes(display); + CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); + CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; + + CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE); + // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef + + int ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; + DBG_PRINT( "setScreenMode0: scrn %d (%p, %p), mode %d, rot %d ccw, avail: %d/%d\n", + (int)scrn_idx, screen, (void*)(intptr_t)display, (int)mode_idx, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); + + if(ccwRot!=0) { + // FIXME: How to rotate the display/screen on OSX programmatically ? + DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot); + res = JNI_FALSE; + } + if(JNI_TRUE == res) { + CGError err = CGDisplaySwitchToMode(display, mode); + if(kCGErrorSuccess != err) { + DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err); + res = JNI_FALSE; + } + } + + // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef + [pool release]; + + return res; +} + /* * Class: jogamp_newt_driver_macosx_MacWindow * Method: initIDs @@ -272,11 +479,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); - if(NULL==focusActionID) { - NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch method focusAction()Z"); - } - // 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"); @@ -449,8 +651,9 @@ NS_DURING if([mView isInFullScreenMode]) { [mView exitFullScreenModeWithOptions: NULL]; } - [mWin setContentView: nil]; - [mView release]; + // Note: mWin's release will also release it's mView! + // [mWin setContentView: nil]; + // [mView release]; } NS_HANDLER NS_ENDHANDLER @@ -463,7 +666,11 @@ NS_ENDHANDLER DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); - [mWin close]; // performs release! + // '[mWin close]' causes a crash at exit. + // This probably happens b/c it sends events to the main loop + // but our resources are gone ?! + // However, issuing a simple release seems to work quite well. + [mWin release]; DBG_PRINT( "windowClose.X - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -510,26 +717,44 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 (JNIEnv *env, jobject window, jlong w, jboolean force) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSWindow* win = (NSWindow*) ((intptr_t) w); + NSWindow* mWin = (NSWindow*) ((intptr_t) w); #ifdef VERBOSE_ON - BOOL hasFocus = [win isKeyWindow]; + BOOL hasFocus = [mWin isKeyWindow]; #endif - DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", win, force, hasFocus); - - // Even if we already own the focus, we need the 'focusAction()' call - // and the other probably redundant NS calls to force proper focus traversal - // of the parent TK (AWT doesn't do it properly on OSX). - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - DBG_PRINT( "makeKeyWindow win %p\n", win); - // [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // [win performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - [win orderFrontRegardless]; - [win makeKeyWindow]; - [win makeFirstResponder: nil]; - } + DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); + + [mWin makeFirstResponder: nil]; + // [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; + // [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; + [mWin orderFrontRegardless]; + [mWin makeKeyWindow]; + + DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); + + [pool release]; +} - DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", win, force); +/* + * Class: jogamp_newt_driver_macosx_MacWindow + * Method: requestFocusParent0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 + (JNIEnv *env, jobject window, jlong w) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* mWin = (NSWindow*) ((intptr_t) w); + NSWindow* pWin = [mWin parentWindow]; +#ifdef VERBOSE_ON + BOOL hasFocus = [mWin isKeyWindow]; +#endif + + DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if(NULL != pWin) { + [pWin makeKeyWindow]; + } + DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); [pool release]; } diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h index e9c0476ef..59d63cecf 100644 --- a/src/newt/native/MouseEvent.h +++ b/src/newt/native/MouseEvent.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef _MOUSE_EVENT_H_ #define _MOUSE_EVENT_H_ diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 91fceb310..33aba64ae 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef NEWT_COMMON_H #define NEWT_COMMON_H 1 diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index cb256e71f..3ba89de1e 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -40,7 +41,8 @@ // #define VERBOSE_ON 1 #ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) + #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) + // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) #else #define DBG_PRINT(...) #endif @@ -53,8 +55,8 @@ JavaVM *jvmHandle; int jvmVersion; - BOOL destroyNotifySent; - BOOL softLocked; + volatile BOOL destroyNotifySent; + volatile BOOL softLocked; pthread_mutex_t softLockSync; NSTrackingRectTag ptrTrackingTag; @@ -88,7 +90,7 @@ - (BOOL) needsDisplay; - (void) displayIfNeeded; -- (void) viewWillDraw; +- (void) display; - (void) drawRect:(NSRect)dirtyRect; - (void) viewDidHide; - (void) viewDidUnhide; diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index 1f74742ec..ce41673c4 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -44,15 +44,17 @@ jint GetDeltaY(NSEvent *event, jint javaMods) { // mouse pad case deltaY = CGEventGetIntegerValueField(cgEvent, kCGScrollWheelEventPointDeltaAxis1); + // fprintf(stderr, "WHEEL/PAD: %lf\n", (double)deltaY); } else { // traditional mouse wheel case deltaY = [event deltaY]; + // fprintf(stderr, "WHEEL/TRAD: %lf\n", (double)deltaY); if (deltaY == 0.0 && (javaMods & EVENT_SHIFT_MASK) != 0) { // shift+vertical wheel scroll produces horizontal scroll // we convert it to vertical deltaY = [event deltaX]; } - if (deltaY < 1.0 && deltaY > -1.0) { + if (-1.0 < deltaY && deltaY < 1.0) { deltaY *= 10.0; } else { if (deltaY < 0.0) { @@ -62,21 +64,15 @@ jint GetDeltaY(NSEvent *event, jint javaMods) { } } } - - if (deltaY > 0) { - return (NSInteger)deltaY; - } else if (deltaY < 0) { - return -(NSInteger)deltaY; - } - - return 0; + // fprintf(stderr, "WHEEL/res: %d\n", (int)deltaY); + return (jint) deltaY; } static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; static jmethodID sendKeyEventID = NULL; -static jmethodID enqueueRequestFocusID = NULL; +static jmethodID requestFocusID = NULL; static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; @@ -104,7 +100,11 @@ static jmethodID windowRepaintID = NULL; jvmVersion = 0; destroyNotifySent = NO; softLocked = NO; - pthread_mutex_init(&softLockSync, NULL); // fast non-recursive + + pthread_mutexattr_t softLockSyncAttr; + pthread_mutexattr_init(&softLockSyncAttr); + pthread_mutexattr_settype(&softLockSyncAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive ptrTrackingTag = 0; @@ -122,7 +122,7 @@ static jmethodID windowRepaintID = NULL; - (void) dealloc { if(softLocked) { - fprintf(stderr, "*** Warning: softLock still hold @ dealloc!\n"); fflush(NULL); + NSLog(@"NewtView::dealloc: softLock still hold @ dealloc!\n"); } pthread_mutex_destroy(&softLockSync); [super dealloc]; @@ -193,72 +193,61 @@ static jmethodID windowRepaintID = NULL; return destroyNotifySent; } -#define SOFT_LOCK_BLOCKING 1 - - (BOOL) softLock { + // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self()); + // NSLog(@"NewtView::softLock: %@",[NSThread callStackSymbols]); pthread_mutex_lock(&softLockSync); softLocked = YES; -#ifndef SOFT_LOCK_BLOCKING - pthread_mutex_unlock(&softLockSync); -#endif + // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self()); return softLocked; } - (void) softUnlock { -#ifndef SOFT_LOCK_BLOCKING - pthread_mutex_lock(&softLockSync); -#endif + // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self()); softLocked = NO; pthread_mutex_unlock(&softLockSync); } - (BOOL) needsDisplay { -#ifndef SOFT_LOCK_BLOCKING - return NO == softLocked && NO == destroyNotifySent && [super needsDisplay]; -#else return NO == destroyNotifySent && [super needsDisplay]; -#endif } - (void) displayIfNeeded { -#ifndef SOFT_LOCK_BLOCKING - if( NO == softLocked && NO == destroyNotifySent ) { + if( YES == [self needsDisplay] ) { + [self softLock]; [super displayIfNeeded]; + [self softUnlock]; } -#else - [self softLock]; - if( NO == destroyNotifySent ) { - [super displayIfNeeded]; - } - [self softUnlock]; -#endif } -- (void) viewWillDraw +- (void) display { - DBG_PRINT("*************** viewWillDraw: 0x%p\n", javaWindowObject); - [super viewWillDraw]; + if( NO == destroyNotifySent ) { + [self softLock]; + [super display]; + [self softUnlock]; + } } - (void) drawRect:(NSRect)dirtyRect { - DBG_PRINT("*************** dirtyRect: 0x%p %lf/%lf %lfx%lf\n", + DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n", javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } NSRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_FALSE, + (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer .. dirtyRect.origin.x, viewFrame.size.height - dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); @@ -272,7 +261,7 @@ static jmethodID windowRepaintID = NULL; int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } @@ -290,7 +279,7 @@ static jmethodID windowRepaintID = NULL; int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); if(NULL==env) { - NSLog(@"viewDidHide: null JNIEnv"); + DBG_PRINT("viewDidHide: null JNIEnv\n"); return; } @@ -325,9 +314,9 @@ static jmethodID windowRepaintID = NULL; focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); + requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (enqueueMouseEventID && sendMouseEventID && enqueueKeyEventID && sendKeyEventID && sizeChangedID && visibleChangedID && insetsChangedID && - positionChangedID && focusChangedID && windowDestroyNotifyID && enqueueRequestFocusID && windowRepaintID) + positionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) { return YES; } @@ -512,14 +501,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"sendKeyEvent: null javaWindowObject"); + DBG_PRINT("sendKeyEvent: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"sendKeyEvent: null JNIEnv"); + DBG_PRINT("sendKeyEvent: null JNIEnv\n"); return; } @@ -533,6 +522,8 @@ static jint mods2JavaMods(NSUInteger mods) // Note: the key code in the NSEvent does not map to anything we can use jchar keyChar = (jchar) [chars characterAtIndex: i]; + DBG_PRINT("sendKeyEvent: %d/%d char 0x%X, code 0x%X\n", i, len, (int)keyChar, (int)keyCode); + #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, evType, javaMods, keyCode, keyChar); @@ -567,14 +558,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"sendMouseEvent: null javaWindowObject"); + DBG_PRINT("sendMouseEvent: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"sendMouseEvent: null JNIEnv"); + DBG_PRINT("sendMouseEvent: null JNIEnv\n"); return; } jint javaMods = mods2JavaMods([event modifierFlags]); @@ -586,6 +577,7 @@ static jint mods2JavaMods(NSUInteger mods) switch ([event type]) { case NSScrollWheel: { scrollDeltaY = GetDeltaY(event, javaMods); + javaButtonNum = 1; break; } case NSLeftMouseDown: @@ -603,9 +595,6 @@ static jint mods2JavaMods(NSUInteger mods) case NSOtherMouseDragged: javaButtonNum = 2; break; - default: - javaButtonNum = 0; - break; } if (evType == EVENT_MOUSE_WHEEL_MOVED && scrollDeltaY == 0) { @@ -613,7 +602,7 @@ static jint mods2JavaMods(NSUInteger mods) return; } if (evType == EVENT_MOUSE_PRESSED) { - (*env)->CallVoidMethod(env, javaWindowObject, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, javaWindowObject, requestFocusID, JNI_FALSE); } NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; @@ -770,14 +759,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"windowDidResize: null javaWindowObject"); + DBG_PRINT("windowDidResize: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowDidResize: null JNIEnv"); + DBG_PRINT("windowDidResize: null JNIEnv\n"); return; } @@ -805,14 +794,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"windowDidMove: null javaWindowObject"); + DBG_PRINT("windowDidMove: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowDidMove: null JNIEnv"); + DBG_PRINT("windowDidMove: null JNIEnv\n"); return; } @@ -839,16 +828,16 @@ static jint mods2JavaMods(NSUInteger mods) if( false == [view getDestroyNotifySent] ) { jobject javaWindowObject = [view getJavaWindowObject]; - DBG_PRINT( "*************** windowWillClose.0: 0x%p\n", (void *)(intptr_t)javaWindowObject); + DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { - NSLog(@"windowWillClose: null javaWindowObject"); + DBG_PRINT("windowWillClose: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"windowWillClose: null JNIEnv"); + DBG_PRINT("windowWillClose: null JNIEnv\n"); return; } @@ -863,7 +852,7 @@ static jint mods2JavaMods(NSUInteger mods) if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); } - DBG_PRINT( "*************** windowWillClose.X: 0x%p\n", (void *)(intptr_t)javaWindowObject); + DBG_PRINT( "*************** windowWillClose.X: %p\n", (void *)(intptr_t)javaWindowObject); } else { DBG_PRINT( "*************** windowWillClose (skip)\n"); } @@ -916,14 +905,14 @@ static jint mods2JavaMods(NSUInteger mods) NewtView* view = (NewtView *) nsview; jobject javaWindowObject = [view getJavaWindowObject]; if (javaWindowObject == NULL) { - NSLog(@"focusChanged: null javaWindowObject"); + DBG_PRINT("focusChanged: null javaWindowObject\n"); return; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { - NSLog(@"focusChanged: null JNIEnv"); + DBG_PRINT("focusChanged: null JNIEnv\n"); return; } diff --git a/src/newt/native/ScreenMode.h b/src/newt/native/ScreenMode.h index 0a760d54a..bb782910e 100644 --- a/src/newt/native/ScreenMode.h +++ b/src/newt/native/ScreenMode.h @@ -1,4 +1,32 @@ /** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +/** * WARNING: must be synced with com.jogamp.newt.util.ScreenModeUtil#streamIn*(int[]) */ diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index 865746b91..4755c4fc5 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef _WINDOW_H_ #define _WINDOW_H_ diff --git a/src/newt/native/WindowEvent.h b/src/newt/native/WindowEvent.h index 05491b43c..3dc6ba97e 100644 --- a/src/newt/native/WindowEvent.h +++ b/src/newt/native/WindowEvent.h @@ -1,3 +1,30 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ #ifndef _WINDOW_EVENT_H_ #define _WINDOW_EVENT_H_ diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index d60c40496..97fe6f28d 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -115,8 +115,7 @@ static jmethodID enqueueMouseEventID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID enqueueKeyEventID = NULL; static jmethodID sendKeyEventID = NULL; -static jmethodID focusActionID = NULL; -static jmethodID enqueueRequestFocusID = NULL; +static jmethodID requestFocusID = NULL; static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd); @@ -602,18 +601,14 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jb (void*) pHwnd, (void*)hwnd, current==hwnd); if( JNI_TRUE==force || current!=hwnd) { - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); - SetForegroundWindow(hwnd); // Slightly Higher Priority - SetFocus(hwnd);// Sets Keyboard Focus To Window - if(NULL!=pHwnd) { - SetActiveWindow(hwnd); - } - DBG_PRINT("*** WindowsWindow: requestFocus.X1\n"); - } else { - DBG_PRINT("*** WindowsWindow: requestFocus.X0\n"); + UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); + SetForegroundWindow(hwnd); // Slightly Higher Priority + SetFocus(hwnd);// Sets Keyboard Focus To Window + if(NULL!=pHwnd) { + SetActiveWindow(hwnd); } + DBG_PRINT("*** WindowsWindow: requestFocus.X1\n"); } DBG_PRINT("*** WindowsWindow: requestFocus.XX\n"); } @@ -870,11 +865,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, case WM_LBUTTONDOWN: DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 1, (jint) 0); useDefWindowProc = 1; break; @@ -883,18 +878,18 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 1, (jint) 0); useDefWindowProc = 1; break; case WM_MBUTTONDOWN: DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 2, (jint) 0); useDefWindowProc = 1; break; @@ -903,18 +898,18 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 2, (jint) 0); useDefWindowProc = 1; break; case WM_RBUTTONDOWN: DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, enqueueRequestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 3, (jint) 0); useDefWindowProc = 1; break; @@ -923,7 +918,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 3, (jint) 0); useDefWindowProc = 1; break; @@ -932,7 +927,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, GetModifiers(), - (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jint) 0, (jint) 0); useDefWindowProc = 1; break; @@ -958,7 +953,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (jint) EVENT_MOUSE_WHEEL_MOVED, GetModifiers(), (jint) eventPt.x, (jint) eventPt.y, - (jint) 0, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f)); + (jint) 1, (jint) (GET_WHEEL_DELTA_WPARAM(wParam)/120.0f)); useDefWindowProc = 1; break; } @@ -978,8 +973,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_MOVE: - DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, (int)LOWORD(lParam), (int)HIWORD(lParam)); - (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)LOWORD(lParam), (jint)HIWORD(lParam)); + DBG_PRINT("*** WindowsWindow: WM_MOVE window %p, %d/%d\n", wnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + (*env)->CallVoidMethod(env, window, positionChangedID, JNI_FALSE, (jint)GET_X_LPARAM(lParam), (jint)GET_Y_LPARAM(lParam)); useDefWindowProc = 1; break; @@ -1046,13 +1041,47 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsDisplay_DispatchMe /* * Class: jogamp_newt_driver_windows_WindowsScreen + * Method: getOriginX0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginX0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + if( GetSystemMetrics( SM_CMONITORS) > 1) { + return (jint)GetSystemMetrics(SM_XVIRTUALSCREEN); + } else { + return 0; + } +} + +/* + * Class: jogamp_newt_driver_windows_WindowsScreen + * Method: getOriginY0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getOriginY0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + if( GetSystemMetrics( SM_CMONITORS ) > 1) { + return (jint)GetSystemMetrics(SM_YVIRTUALSCREEN); + } else { + return 0; + } +} + +/* + * Class: jogamp_newt_driver_windows_WindowsScreen * Method: getWidthImpl * Signature: (I)I */ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { - return (jint)GetSystemMetrics(SM_CXSCREEN); + if( GetSystemMetrics( SM_CMONITORS) > 1) { + return (jint)GetSystemMetrics(SM_CXVIRTUALSCREEN); + } else { + return (jint)GetSystemMetrics(SM_CXSCREEN); + } } /* @@ -1063,7 +1092,11 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getWidthImp JNIEXPORT jint JNICALL Java_jogamp_newt_driver_windows_WindowsScreen_getHeightImpl0 (JNIEnv *env, jobject obj, jint scrn_idx) { - return (jint)GetSystemMetrics(SM_CYSCREEN); + if( GetSystemMetrics( SM_CMONITORS ) > 1) { + return (jint)GetSystemMetrics(SM_CYVIRTUALSCREEN); + } else { + return (jint)GetSystemMetrics(SM_CYSCREEN); + } } static int NewtScreen_RotationNativeCCW2NewtCCW(JNIEnv *env, int native) { @@ -1270,8 +1303,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); + requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (insetsChangedID == NULL || sizeChangedID == NULL || @@ -1284,8 +1316,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_initIDs sendMouseEventID == NULL || enqueueKeyEventID == NULL || sendKeyEventID == NULL || - focusActionID == NULL || - enqueueRequestFocusID == NULL) { + requestFocusID == NULL) { return JNI_FALSE; } BuildDynamicKeyMapTable(); @@ -1317,9 +1348,6 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, } else { flags = SWP_NOACTIVATE | SWP_NOZORDER; } - if(0>x || 0>y) { - flags |= SWP_NOMOVE; - } if(0>=width || 0>=height ) { flags |= SWP_NOSIZE; } @@ -1345,7 +1373,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind (JNIEnv *env, jobject obj, jlong hInstance, jstring jWndClassName, jstring jWndName, jlong parent, - jint jx, jint jy, jint defaultWidth, jint defaultHeight, jint flags) + jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags) { HWND parentWindow = (HWND) (intptr_t) parent; const TCHAR* wndClassName = NULL; @@ -1374,7 +1402,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; } else { windowStyle |= WS_OVERLAPPEDWINDOW; - if(0>_x || 0>_y) { + if(JNI_TRUE == autoPosition) { // user didn't requested specific position, use WM default _x = CW_USEDEFAULT; _y = 0; @@ -1387,9 +1415,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind (HINSTANCE) (intptr_t) hInstance, NULL); - DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d\n", + DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags)); + TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); if (NULL == window) { int lastError = (int) GetLastError(); @@ -1409,7 +1437,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind { RECT rc; RECT * insets; - BOOL userPos = 0<=x && 0<=y ; ShowWindow(window, SW_SHOW); @@ -1417,12 +1444,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_CreateWind insets = UpdateInsets(env, wud->jinstance, window); (*env)->CallVoidMethod(env, wud->jinstance, visibleChangedID, JNI_FALSE, JNI_TRUE); - if(!userPos) { + if(JNI_TRUE == autoPosition) { GetWindowRect(window, &rc); x = rc.left + insets->left; // client coords y = rc.top + insets->top; // client coords } - DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos); + DBG_PRINT("*** WindowsWindow: CreateWindow client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); x -= insets->left; // top-level y -= insets->top; // top-level diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h new file mode 100644 index 000000000..cefef690f --- /dev/null +++ b/src/newt/native/X11Common.h @@ -0,0 +1,80 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +#ifndef _X11COMMON_H_ +#define _X11COMMON_H_ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include <gluegen_stdint.h> + +#include <unistd.h> +#include <errno.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> + +#include <X11/extensions/Xrandr.h> + +#include "jogamp_newt_driver_x11_X11Screen.h" +#include "jogamp_newt_driver_x11_X11Display.h" +#include "jogamp_newt_driver_x11_X11Window.h" + +#include "Window.h" +#include "MouseEvent.h" +#include "InputEvent.h" +#include "KeyEvent.h" +#include "WindowEvent.h" +#include "ScreenMode.h" + +#include "NewtCommon.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif + +extern jclass X11NewtWindowClazz; +extern jmethodID insetsChangedID; +extern jmethodID visibleChangedID; + +jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning); + +void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env); +Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return); +Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom); + +#endif /* _X11COMMON_H_ */ + diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c new file mode 100644 index 000000000..283636040 --- /dev/null +++ b/src/newt/native/X11Display.c @@ -0,0 +1,660 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +#include "X11Common.h" + +#define USE_SENDIO_DIRECT 1 + +jclass X11NewtWindowClazz = NULL; +jmethodID insetsChangedID = NULL; +jmethodID visibleChangedID = NULL; + +static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/X11Window"; + +static jmethodID displayCompletedID = NULL; + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID focusChangedID = NULL; +static jmethodID reparentNotifyID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowRepaintID = NULL; +static jmethodID enqueueMouseEventID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID enqueueKeyEventID = NULL; +static jmethodID sendKeyEventID = NULL; +static jmethodID requestFocusID = NULL; + +static JavaVM *jvmHandle = NULL; +static int jvmVersion = 0; + +static void setupJVMVars(JNIEnv * env) { + if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { + jvmHandle = NULL; + } + jvmVersion = (*env)->GetVersion(env); +} + +static XErrorHandler origErrorHandler = NULL ; + +static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e) +{ + fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno)); + + if (e->error_code == BadAtom) { + fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid); + } else if (e->error_code == BadWindow) { + fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid); + } else { + int shallBeDetached = 0; + JNIEnv *jniEnv = NULL; + const char * errStr = strerror(errno); + + fprintf(stderr, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr); + + jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); + if(NULL==jniEnv) { + fprintf(stderr, "NEWT X11 Error: null JNIEnv"); + return; + } + + NewtCommon_throwNewRuntimeException(jniEnv, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s", + dpy, e->error_code, errStr); + + if (shallBeDetached) { + (*jvmHandle)->DetachCurrentThread(jvmHandle); + } + } + + return 0; +} + +void NewtDisplay_displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) { + if(onoff) { + if(NULL==origErrorHandler) { + setupJVMVars(env); + origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler); + } + } else { + if(NULL!=origErrorHandler) { + XSetErrorHandler(origErrorHandler); + origErrorHandler = NULL; + } + } +} + +/** + * Keycode + */ + +#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b)) + +static jint X11KeySym2NewtVKey(KeySym keySym) { + if(IS_WITHIN(keySym,XK_F1,XK_F12)) + return (keySym-XK_F1)+J_VK_F1; + if(IS_WITHIN(keySym,XK_KP_0,XK_KP_9)) + return (keySym-XK_KP_0)+J_VK_NUMPAD0; + + switch(keySym) { + case XK_Return: + case XK_KP_Enter: + return J_VK_ENTER; + case XK_BackSpace: + return J_VK_BACK_SPACE; + case XK_Tab: + case XK_KP_Tab: + case XK_ISO_Left_Tab: + return J_VK_TAB; + case XK_Cancel: + return J_VK_CANCEL; + case XK_Clear: + return J_VK_CLEAR; + case XK_Shift_L: + case XK_Shift_R: + return J_VK_SHIFT; + case XK_Control_L: + case XK_Control_R: + return J_VK_CONTROL; + case XK_Alt_L: + case XK_Alt_R: + return J_VK_ALT; + case XK_Pause: + return J_VK_PAUSE; + case XK_Caps_Lock: + return J_VK_CAPS_LOCK; + case XK_Escape: + return J_VK_ESCAPE; + case XK_space: + case XK_KP_Space: + return J_VK_SPACE; + case XK_Page_Up: + case XK_KP_Page_Up: + return J_VK_PAGE_UP; + case XK_Page_Down: + case XK_KP_Page_Down: + return J_VK_PAGE_DOWN; + case XK_End: + case XK_KP_End: + return J_VK_END; + case XK_Home: + case XK_KP_Home: + return J_VK_HOME; + case XK_Left: + case XK_KP_Left: + return J_VK_LEFT; + case XK_Up: + case XK_KP_Up: + return J_VK_UP; + case XK_Right: + case XK_KP_Right: + return J_VK_RIGHT; + case XK_Down: + case XK_KP_Down: + return J_VK_DOWN; + case XK_KP_Multiply: + return J_VK_MULTIPLY; + case XK_KP_Add: + return J_VK_ADD; + case XK_KP_Separator: + return J_VK_SEPARATOR; + case XK_KP_Subtract: + return J_VK_SUBTRACT; + case XK_KP_Decimal: + return J_VK_DECIMAL; + case XK_KP_Divide: + return J_VK_DIVIDE; + case XK_Delete: + case XK_KP_Delete: + return J_VK_DELETE; + case XK_Num_Lock: + return J_VK_NUM_LOCK; + case XK_Scroll_Lock: + return J_VK_SCROLL_LOCK; + case XK_Print: + return J_VK_PRINTSCREEN; + case XK_Insert: + case XK_KP_Insert: + return J_VK_INSERT; + case XK_Help: + return J_VK_HELP; + } + return keySym; +} + +static jint X11InputState2NewtModifiers(unsigned int xstate) { + jint modifiers = 0; + if ((ControlMask & xstate) != 0) { + modifiers |= EVENT_CTRL_MASK; + } + if ((ShiftMask & xstate) != 0) { + modifiers |= EVENT_SHIFT_MASK; + } + if ((Mod1Mask & xstate) != 0) { + modifiers |= EVENT_ALT_MASK; + } + if ((Button1Mask & xstate) != 0) { + modifiers |= EVENT_BUTTON1_MASK; + } + if ((Button2Mask & xstate) != 0) { + modifiers |= EVENT_BUTTON2_MASK; + } + if ((Button3Mask & xstate) != 0) { + modifiers |= EVENT_BUTTON3_MASK; + } + + return modifiers; +} + + +/** + * Keycode + */ + +/* + * Class: jogamp_newt_driver_x11_X11Display + * Method: initIDs + * Signature: (Z)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 + (JNIEnv *env, jclass clazz) +{ + jclass c; + + NewtCommon_init(env); + + if(NULL==X11NewtWindowClazz) { + c = (*env)->FindClass(env, ClazzNameX11NewtWindow); + if(NULL==c) { + NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameX11NewtWindow); + } + X11NewtWindowClazz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==X11NewtWindowClazz) { + NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameX11NewtWindow); + } + } + + displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V"); + insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V"); + sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZIIZ)V"); + positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V"); + focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V"); + visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V"); + reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "()V"); + windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); + enqueueMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueMouseEvent", "(ZIIIIII)V"); + sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(IIIIII)V"); + enqueueKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "enqueueKeyEvent", "(ZIIIC)V"); + sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(IIIC)V"); + requestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "requestFocus", "(Z)V"); + + if (displayCompletedID == NULL || + insetsChangedID == NULL || + sizeChangedID == NULL || + positionChangedID == NULL || + focusChangedID == NULL || + visibleChangedID == NULL || + reparentNotifyID == NULL || + windowDestroyNotifyID == NULL || + windowRepaintID == NULL || + enqueueMouseEventID == NULL || + sendMouseEventID == NULL || + enqueueKeyEventID == NULL || + sendKeyEventID == NULL || + requestFocusID == NULL) { + return JNI_FALSE; + } + + + return JNI_TRUE; +} + +/* + * Class: jogamp_newt_driver_x11_X11Display + * Method: CompleteDisplay + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0 + (JNIEnv *env, jobject obj, jlong display) +{ + Display * dpy = (Display *)(intptr_t)display; + jlong javaObjectAtom; + jlong windowDeleteAtom; + + if(dpy==NULL) { + NewtCommon_FatalError(env, "invalid display connection.."); + } + + javaObjectAtom = (jlong) XInternAtom(dpy, "NEWT_JAVA_OBJECT", False); + if(None==javaObjectAtom) { + NewtCommon_throwNewRuntimeException(env, "could not create Atom NEWT_JAVA_OBJECT, bail out!"); + return; + } + + windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False); + if(None==windowDeleteAtom) { + NewtCommon_throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!"); + return; + } + + // XSetCloseDownMode(dpy, RetainTemporary); // Just a try .. + + DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy); + + (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); +} + +/* + * Class: jogamp_newt_driver_x11_X11Display + * Method: DisplayRelease0 + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0 + (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) +{ + Display * dpy = (Display *)(intptr_t)display; + Atom wm_javaobject_atom = (Atom)javaObjectAtom; + Atom wm_delete_atom = (Atom)windowDeleteAtom; + + if(dpy==NULL) { + NewtCommon_FatalError(env, "invalid display connection.."); + } + + // nothing to do to free the atoms ! + (void) wm_javaobject_atom; + (void) wm_delete_atom; + + XSync(dpy, True); // discard all pending events + DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy); +} + +/* + * Class: jogamp_newt_driver_x11_X11Display + * Method: DispatchMessages + * Signature: (JIJJ)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0 + (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) +{ + Display * dpy = (Display *) (intptr_t) display; + Atom wm_delete_atom = (Atom)windowDeleteAtom; + int num_events = 100; + + if ( NULL == dpy ) { + return; + } + + // Periodically take a break + while( num_events > 0 ) { + jobject jwindow = NULL; + XEvent evt; + KeySym keySym = 0; + jint modifiers = 0; + char keyChar = 0; + char text[255]; + + // XEventsQueued(dpy, X): + // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?) + // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available + // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more .. + if ( 0 >= XPending(dpy) ) { + // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy); + return; + } + + XNextEvent(dpy, &evt); + num_events--; + + if( 0==evt.xany.window ) { + NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!"); + return ; + } + + if(dpy!=evt.xany.display) { + NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!"); + return ; + } + + // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); + + NewtDisplay_displayDispatchErrorHandlerEnable(1, env); + + jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + #ifdef VERBOSE_ON + True + #else + False + #endif + ); + + NewtDisplay_displayDispatchErrorHandlerEnable(0, env); + + if(NULL==jwindow) { + fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", + (void*)dpy, evt.type, (void*)evt.xany.window); + continue; + } + + switch(evt.type) { + case KeyRelease: + case KeyPress: + if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { + KeySym lower_return = 0, upper_return = 0; + keyChar=text[0]; + XConvertCase(keySym, &lower_return, &upper_return); + // always return upper case, set modifier masks (SHIFT, ..) + keySym = X11KeySym2NewtVKey(upper_return); + } else { + keyChar=0; + keySym = X11KeySym2NewtVKey(keySym); + } + modifiers = X11InputState2NewtModifiers(evt.xkey.state); + break; + + case ButtonPress: + case ButtonRelease: + case MotionNotify: + modifiers = X11InputState2NewtModifiers(evt.xbutton.state); + break; + + default: + break; + } + + switch(evt.type) { + case ButtonPress: + (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE); + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #endif + break; + case ButtonRelease: + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + #endif + break; + case MotionNotify: + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + modifiers, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, + modifiers, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); + #endif + break; + case EnterNotify: + DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #endif + break; + case LeaveNotify: + DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #endif + break; + case KeyPress: + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + modifiers, keySym, (jchar) -1); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, + modifiers, keySym, (jchar) -1); + #endif + + break; + case KeyRelease: + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + modifiers, keySym, (jchar) -1); + + (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, + modifiers, keySym, (jchar) keyChar); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, + modifiers, keySym, (jchar) -1); + + (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, + modifiers, keySym, (jchar) keyChar); + #endif + + break; + case DestroyNotify: + DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", + (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event); + if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) { + // ignore child destroy notification + } + break; + case CreateNotify: + DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n", + (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent); + break; + case ConfigureNotify: + DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n", + (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above, + evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height, + evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); + if ( evt.xconfigure.window == evt.xconfigure.event ) { + // ignore child window change notification + { + // update insets + int left, right, top, bottom; + NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + } + (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE, + (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); + (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE, + (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); + } + break; + case ClientMessage: + if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom + DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n", + (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); + (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID); + // Called by Window.java: CloseWindow(); + num_events = 0; // end loop in case of destroyed display + } + break; + + case FocusIn: + DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); + (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); + break; + + case FocusOut: + DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); + (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); + break; + + case Expose: + DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); + + if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { + (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + } + break; + + case MapNotify: + DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n", + (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect, + evt.xmap.event!=evt.xmap.window); + if( evt.xmap.event == evt.xmap.window ) { + // ignore child window notification + { + // update insets + int left, right, top, bottom; + NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); + } + (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); + } + break; + + case UnmapNotify: + DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n", + (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure, + evt.xunmap.event!=evt.xunmap.window); + if( evt.xunmap.event == evt.xunmap.window ) { + // ignore child window notification + (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); + } + break; + + case ReparentNotify: + { + jlong parentResult; // 0 if root, otherwise proper value + Window winRoot, winTopParent; + #ifdef VERBOSE_ON + Window oldParentRoot, oldParentTopParent; + Window parentRoot, parentTopParent; + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) { + oldParentRoot=0; oldParentTopParent = 0; + } + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) { + parentRoot=0; parentTopParent = 0; + } + #endif + if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) { + winRoot=0; winTopParent = 0; + } + if(evt.xreparent.parent == winRoot) { + parentResult = 0; // our java indicator for root window + } else { + parentResult = (jlong) (intptr_t) evt.xreparent.parent; + } + #ifdef VERBOSE_ON + DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n", + evt.xreparent.x, evt.xreparent.y, + (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent, + (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, + (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); + #endif + (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); + } + break; + + // unhandled events .. yet .. + + default: + DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window); + } + } +} + + diff --git a/src/newt/native/X11Screen.c b/src/newt/native/X11Screen.c new file mode 100644 index 000000000..1b7fea770 --- /dev/null +++ b/src/newt/native/X11Screen.c @@ -0,0 +1,469 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +#include "X11Common.h" + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: GetScreen + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_index) +{ + Display * dpy = (Display *)(intptr_t)display; + Screen * scrn= NULL; + + DBG_PRINT("X11: X11Screen_GetScreen0 dpy %p START\n", dpy); + + if(dpy==NULL) { + NewtCommon_FatalError(env, "invalid display connection.."); + } + + scrn = ScreenOfDisplay(dpy, screen_index); + if(scrn==NULL) { + fprintf(stderr, "couldn't get screen idx %d\n", screen_index); + } + DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn); + return (jlong) (intptr_t) scrn; +} + +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) DisplayWidth( dpy, scrn_idx); +} + +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) DisplayHeight( dpy, scrn_idx); +} + +static int showedRandRVersion = 0; + +static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) { + if( 0 == XRRQueryVersion(dpy, major, minor) ) { + return False; + } + if(0 == showedRandRVersion) { + fprintf(stderr, "X11 RandR Version %d.%d\n", *major, *minor); + showedRandRVersion = 1; + } + return True; +} + +static Bool NewtScreen_hasRANDR(Display *dpy) { + int major, minor; + return NewtScreen_getRANDRVersion(dpy, &major, &minor); +} + +static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { + int rot; + if(xrotation == RR_Rotate_0) { + rot = 0; + } + else if(xrotation == RR_Rotate_90) { + rot = 90; + } + else if(xrotation == RR_Rotate_180) { + rot = 180; + } + else if(xrotation == RR_Rotate_270) { + rot = 270; + } else { + NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation); + } + return rot; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getAvailableScreenModeRotations0 + * Signature: (JI)I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + int num_rotations = 0; + Rotation cur_rotation, rotations_supported; + int rotations[4]; + int major, minor; + + if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) { + fprintf(stderr, "RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation); + + if(0 != (rotations_supported & RR_Rotate_0)) { + rotations[num_rotations++] = 0; + } + if(0 != (rotations_supported & RR_Rotate_90)) { + rotations[num_rotations++] = 90; + } + if(0 != (rotations_supported & RR_Rotate_180)) { + rotations[num_rotations++] = 180; + } + if(0 != (rotations_supported & RR_Rotate_270)) { + rotations[num_rotations++] = 270; + } + + jintArray properties = NULL; + + if(num_rotations>0) { + properties = (*env)->NewIntArray(env, num_rotations); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations); + } + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getNumScreenModeResolution0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); + return 0; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes); + + return num_sizes; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getScreenModeResolutions0 + * Signature: (JII)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + // Fill the properties in temp jint array + int propIndex = 0; + jint prop[4]; + + prop[propIndex++] = xrrs[(int)resMode_idx].width; + prop[propIndex++] = xrrs[(int)resMode_idx].height; + prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; + prop[propIndex++] = xrrs[(int)resMode_idx].mheight; + + jintArray properties = (*env)->NewIntArray(env, 4); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, 4, prop); + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getScreenModeRates0 + * Signature: (JII)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); + return (*env)->NewIntArray(env, 0); + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + int num_rates; + short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates); + + jint prop[num_rates]; + int i; + for(i=0; i<num_rates; i++) { + prop[i] = (int) rates[i]; + /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */ + } + + jintArray properties = (*env)->NewIntArray(env, num_rates); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates); + } + + // move from the temp structure to the java structure + (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop); + + return properties; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenRate0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); + return -1; + } + + // get current resolutions and frequencies + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + //free + XRRFreeScreenConfigInfo(conf); + + DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate); + + return (jint) original_rate; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenRotation0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); + return -1; + } + + //get current resolutions and frequencies + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + + Rotation rotation; + XRRConfigCurrentConfiguration(conf, &rotation); + + //free + XRRFreeScreenConfigInfo(conf); + + return NewtScreen_XRotation2Degree(env, rotation); +} + + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: getCurrentScreenResolutionIndex0 + * Signature: (JI)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0 + (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)scrn_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); + return -1; + } + + // get current resolutions and frequency configuration + XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); + short original_rate = XRRConfigCurrentRate(conf); + + Rotation original_rotation; + SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); + + //free + XRRFreeScreenConfigInfo(conf); + + DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id); + return (jint)original_size_id; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: setCurrentScreenModeStart0 + * Signature: (JIIII)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +{ + Display *dpy = (Display *) (intptr_t) display; + Window root = RootWindow(dpy, (int)screen_idx); + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n"); + return JNI_FALSE; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions + XRRScreenConfiguration *conf; + int rot; + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + conf = XRRGetScreenInfo(dpy, root); + + switch(rotation) { + case 0: + rot = RR_Rotate_0; + break; + case 90: + rot = RR_Rotate_90; + break; + case 180: + rot = RR_Rotate_180; + break; + case 270: + rot = RR_Rotate_270; + break; + default: + NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation); + } + + DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", + resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); + + XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); + + XSync(dpy, False); + XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); + XSync(dpy, False); + + //free + XRRFreeScreenConfigInfo(conf); + XSync(dpy, False); + + return JNI_TRUE; +} + +/* + * Class: jogamp_newt_driver_x11_X11Screen + * Method: setCurrentScreenModePollEnd0 + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0 + (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) +{ + Display *dpy = (Display *) (intptr_t) display; + int randr_event_base, randr_error_base; + XEvent evt; + XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; + + if(False == NewtScreen_hasRANDR(dpy)) { + DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); + return JNI_FALSE; + } + + int num_sizes; + XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions + XRRScreenConfiguration *conf; + + if( 0 > resMode_idx || resMode_idx >= num_sizes ) { + NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); + } + + XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); + + int done = 0; + int rot; + do { + if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { + return; + } + XNextEvent(dpy, &evt); + + switch (evt.type - randr_event_base) { + case RRScreenChangeNotify: + rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation); + DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", + (void*)scn_event->window, (void*)scn_event->root, + (int)scn_event->size_index, rot, + scn_event->width, scn_event->height); + // done = scn_event->size_index == resMode_idx; // not reliable .. + done = rot == rotation && + scn_event->width == xrrs[resMode_idx].width && + scn_event->height == xrrs[resMode_idx].height; + break; + default: + DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window); + } + XRRUpdateConfiguration(&evt); + } while(!done); + + XSync(dpy, False); + +} + diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index f14138a0a..0a7e1cf77 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -32,40 +32,9 @@ * */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> - -#include <gluegen_stdint.h> - -#include <unistd.h> -#include <errno.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/keysym.h> -#include <X11/Xatom.h> - -#include <X11/extensions/Xrandr.h> - -#include "jogamp_newt_driver_x11_X11Screen.h" -#include "jogamp_newt_driver_x11_X11Display.h" -#include "jogamp_newt_driver_x11_X11Window.h" - -#include "Window.h" -#include "MouseEvent.h" -#include "InputEvent.h" -#include "KeyEvent.h" -#include "WindowEvent.h" -#include "ScreenMode.h" - -#include "NewtCommon.h" - -// #define VERBOSE_ON 1 +#include "X11Common.h" #ifdef VERBOSE_ON - #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) - #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) static void _dumpVisualInfo(const char * msg, XVisualInfo *pVisualQuery) { @@ -90,259 +59,12 @@ #else - #define DBG_PRINT(...) - #define DUMP_VISUAL_INFO(a,b) #endif -/** - * Keycode - */ - -#define IS_WITHIN(k,a,b) ((a)<=(k)&&(k)<=(b)) - -static jint X11KeySym2NewtVKey(KeySym keySym) { - if(IS_WITHIN(keySym,XK_F1,XK_F12)) - return (keySym-XK_F1)+J_VK_F1; - - switch(keySym) { - case XK_Alt_L: - case XK_Alt_R: - return J_VK_ALT; - - case XK_Left: - return J_VK_LEFT; - case XK_Right: - return J_VK_RIGHT; - case XK_Up: - return J_VK_UP; - case XK_Down: - return J_VK_DOWN; - case XK_Page_Up: - return J_VK_PAGE_UP; - case XK_Page_Down: - return J_VK_PAGE_DOWN; - case XK_Shift_L: - case XK_Shift_R: - return J_VK_SHIFT; - case XK_Control_L: - case XK_Control_R: - return J_VK_CONTROL; - case XK_Escape: - return J_VK_ESCAPE; - case XK_Delete: - return J_VK_DELETE; - } - return keySym; -} - -static jint X11InputState2NewtModifiers(unsigned int xstate) { - jint modifiers = 0; - if ((ControlMask & xstate) != 0) { - modifiers |= EVENT_CTRL_MASK; - } - if ((ShiftMask & xstate) != 0) { - modifiers |= EVENT_SHIFT_MASK; - } - if ((Mod1Mask & xstate) != 0) { - modifiers |= EVENT_ALT_MASK; - } - if ((Button1Mask & xstate) != 0) { - modifiers |= EVENT_BUTTON1_MASK; - } - if ((Button2Mask & xstate) != 0) { - modifiers |= EVENT_BUTTON2_MASK; - } - if ((Button3Mask & xstate) != 0) { - modifiers |= EVENT_BUTTON3_MASK; - } - - return modifiers; -} - #define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask) -static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window"; - -static jclass newtWindowClz=NULL; - -static jmethodID insetsChangedID = NULL; -static jmethodID sizeChangedID = NULL; -static jmethodID positionChangedID = NULL; -static jmethodID focusChangedID = NULL; -static jmethodID visibleChangedID = NULL; -static jmethodID reparentNotifyID = NULL; -static jmethodID windowDestroyNotifyID = NULL; -static jmethodID windowRepaintID = NULL; -static jmethodID enqueueMouseEventID = NULL; -static jmethodID sendMouseEventID = NULL; -static jmethodID enqueueKeyEventID = NULL; -static jmethodID sendKeyEventID = NULL; -static jmethodID focusActionID = NULL; -static jmethodID enqueueRequestFocusID = NULL; - -static jmethodID displayCompletedID = NULL; - - -/** - * Display - */ - -static JavaVM *jvmHandle = NULL; -static int jvmVersion = 0; - -static void setupJVMVars(JNIEnv * env) { - if(0 != (*env)->GetJavaVM(env, &jvmHandle)) { - jvmHandle = NULL; - } - jvmVersion = (*env)->GetVersion(env); -} - -static XErrorHandler origErrorHandler = NULL ; - -static int displayDispatchErrorHandler(Display *dpy, XErrorEvent *e) -{ - fprintf(stderr, "Warning: NEWT X11 Error: DisplayDispatch %p, Code 0x%X, errno %s\n", dpy, e->error_code, strerror(errno)); - - if (e->error_code == BadAtom) { - fprintf(stderr, " BadAtom (%p): Atom probably already removed\n", (void*)e->resourceid); - } else if (e->error_code == BadWindow) { - fprintf(stderr, " BadWindow (%p): Window probably already removed\n", (void*)e->resourceid); - } else { - int shallBeDetached = 0; - JNIEnv *jniEnv = NULL; - const char * errStr = strerror(errno); - - fprintf(stderr, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s\n", dpy, e->error_code, errStr); - - jniEnv = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached); - if(NULL==jniEnv) { - fprintf(stderr, "NEWT X11 Error: null JNIEnv"); - return; - } - - NewtCommon_throwNewRuntimeException(jniEnv, "Info: NEWT X11 Error: Display %p, Code 0x%X, errno %s", - dpy, e->error_code, errStr); - - if (shallBeDetached) { - (*jvmHandle)->DetachCurrentThread(jvmHandle); - } - } - - return 0; -} - -static void displayDispatchErrorHandlerEnable(int onoff, JNIEnv * env) { - if(onoff) { - if(NULL==origErrorHandler) { - setupJVMVars(env); - origErrorHandler = XSetErrorHandler(displayDispatchErrorHandler); - } - } else { - if(NULL!=origErrorHandler) { - XSetErrorHandler(origErrorHandler); - origErrorHandler = NULL; - } - } -} - -/* - * Class: jogamp_newt_driver_x11_X11Display - * Method: initIDs - * Signature: (Z)Z - */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Display_initIDs0 - (JNIEnv *env, jclass clazz) -{ - jclass c; - - NewtCommon_init(env); - - displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJ)V"); - if (displayCompletedID == NULL) { - return JNI_FALSE; - } - - if(NULL==newtWindowClz) { - c = (*env)->FindClass(env, ClazzNameNewtWindow); - if(NULL==c) { - NewtCommon_FatalError(env, "NEWT X11Window: can't find %s", ClazzNameNewtWindow); - } - newtWindowClz = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - if(NULL==newtWindowClz) { - NewtCommon_FatalError(env, "NEWT X11Window: can't use %s", ClazzNameNewtWindow); - } - } - - return JNI_TRUE; -} - -/* - * Class: jogamp_newt_driver_x11_X11Display - * Method: CompleteDisplay - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_CompleteDisplay0 - (JNIEnv *env, jobject obj, jlong display) -{ - Display * dpy = (Display *)(intptr_t)display; - jlong javaObjectAtom; - jlong windowDeleteAtom; - - if(dpy==NULL) { - NewtCommon_FatalError(env, "invalid display connection.."); - } - - javaObjectAtom = (jlong) XInternAtom(dpy, "NEWT_JAVA_OBJECT", False); - if(None==javaObjectAtom) { - NewtCommon_throwNewRuntimeException(env, "could not create Atom NEWT_JAVA_OBJECT, bail out!"); - return; - } - - windowDeleteAtom = (jlong) XInternAtom(dpy, "WM_DELETE_WINDOW", False); - if(None==windowDeleteAtom) { - NewtCommon_throwNewRuntimeException(env, "could not create Atom WM_DELETE_WINDOW, bail out!"); - return; - } - - // XSetCloseDownMode(dpy, RetainTemporary); // Just a try .. - - DBG_PRINT("X11: X11Display_completeDisplay dpy %p\n", dpy); - - (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); -} - -/* - * Class: jogamp_newt_driver_x11_X11Display - * Method: DisplayRelease0 - * Signature: (JJJ)V - */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DisplayRelease0 - (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) -{ - Display * dpy = (Display *)(intptr_t)display; - Atom wm_javaobject_atom = (Atom)javaObjectAtom; - Atom wm_delete_atom = (Atom)windowDeleteAtom; - - if(dpy==NULL) { - NewtCommon_FatalError(env, "invalid display connection.."); - } - - // nothing to do to free the atoms ! - (void) wm_javaobject_atom; - (void) wm_delete_atom; - - XSync(dpy, True); // discard all pending events - DBG_PRINT("X11: X11Display_DisplayRelease dpy %p\n", dpy); -} - - -/** - * Window - */ - static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { int i=0; dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ; @@ -375,7 +97,7 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon (unsigned char *)&jogl_java_object_data, nitems_32); } -static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { +jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { Atom actual_type; int actual_format; int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; @@ -413,7 +135,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j XFree(jogl_java_object_data_pp); #ifdef VERBOSE_ON - if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, newtWindowClz)) { + if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, X11NewtWindowClazz)) { NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow); } #endif @@ -421,7 +143,7 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j } /** @return zero if fails, non zero if OK */ -static Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) { +Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return) { Window *children_return=NULL; unsigned int nchildren_return=0; @@ -502,7 +224,7 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left return 1; // Ok } -static Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { +Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) { if(0 != NewtWindows_getFrameExtends(dpy, window, left, right, top, bottom)) { DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n", *left, *right, *top, *bottom); @@ -535,16 +257,14 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w); if( JNI_TRUE==force || focus_return!=w) { - if( JNI_TRUE==force || JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { - DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); - XRaiseWindow(dpy, w); - NewtWindows_setCWAbove(dpy, w); - // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - XGetWindowAttributes(dpy, w, &xwa); - if(xwa.map_state == IsViewable) { - DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w); - XSetInputFocus(dpy, w, RevertToParent, CurrentTime); - } + DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w); + XRaiseWindow(dpy, w); + NewtWindows_setCWAbove(dpy, w); + // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable + XGetWindowAttributes(dpy, w, &xwa); + if(xwa.map_state == IsViewable) { + DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w); + XSetInputFocus(dpy, w, RevertToParent, CurrentTime); } } DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force); @@ -710,752 +430,6 @@ static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w, return res; } -#define USE_SENDIO_DIRECT 1 - -/* - * Class: jogamp_newt_driver_x11_X11Display - * Method: DispatchMessages - * Signature: (JIJJ)V - */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0 - (JNIEnv *env, jobject obj, jlong display, jlong javaObjectAtom, jlong windowDeleteAtom) -{ - Display * dpy = (Display *) (intptr_t) display; - Atom wm_delete_atom = (Atom)windowDeleteAtom; - int num_events = 100; - - if ( NULL == dpy ) { - return; - } - - // Periodically take a break - while( num_events > 0 ) { - jobject jwindow = NULL; - XEvent evt; - KeySym keySym = 0; - jint modifiers = 0; - char keyChar = 0; - char text[255]; - - // XEventsQueued(dpy, X): - // QueuedAlready : No I/O Flush or system call doesn't work on some cards (eg ATI) ?) - // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available - // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more .. - if ( 0 >= XPending(dpy) ) { - // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy); - return; - } - - XNextEvent(dpy, &evt); - num_events--; - - if( 0==evt.xany.window ) { - NewtCommon_throwNewRuntimeException(env, "event window NULL, bail out!"); - return ; - } - - if(dpy!=evt.xany.display) { - NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!"); - return ; - } - - // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); - - displayDispatchErrorHandlerEnable(1, env); - - jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, - #ifdef VERBOSE_ON - True - #else - False - #endif - ); - - displayDispatchErrorHandlerEnable(0, env); - - if(NULL==jwindow) { - fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", - (void*)dpy, evt.type, (void*)evt.xany.window); - continue; - } - - switch(evt.type) { - case KeyRelease: - case KeyPress: - if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { - KeySym lower_return = 0, upper_return = 0; - keyChar=text[0]; - XConvertCase(keySym, &lower_return, &upper_return); - // always return upper case, set modifier masks (SHIFT, ..) - keySym = upper_return; - modifiers = X11InputState2NewtModifiers(evt.xkey.state); - } else { - keyChar=0; - } - break; - - case ButtonPress: - case ButtonRelease: - case MotionNotify: - modifiers = X11InputState2NewtModifiers(evt.xbutton.state); - break; - - default: - break; - } - - switch(evt.type) { - case ButtonPress: - (*env)->CallVoidMethod(env, jwindow, enqueueRequestFocusID, JNI_FALSE); - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - #endif - break; - case ButtonRelease: - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); - #endif - break; - case MotionNotify: - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, - modifiers, - (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, - modifiers, - (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); - #endif - break; - case EnterNotify: - DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); - #endif - break; - case LeaveNotify: - DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, - modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); - #endif - break; - case KeyPress: - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - #endif - - break; - case KeyRelease: - #ifdef USE_SENDIO_DIRECT - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - - (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, - modifiers, (jint) -1, (jchar) keyChar); - #else - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, - modifiers, X11KeySym2NewtVKey(keySym), (jchar) keyChar); - - (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, - modifiers, (jint) -1, (jchar) keyChar); - #endif - - break; - case DestroyNotify: - DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", - (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event); - if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) { - // ignore child destroy notification - } - break; - case CreateNotify: - DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n", - (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent); - break; - case ConfigureNotify: - DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n", - (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above, - evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height, - evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); - if ( evt.xconfigure.window == evt.xconfigure.event ) { - // ignore child window change notification - { - // update insets - int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); - } - (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE, - (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); - (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE, - (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); - } - break; - case ClientMessage: - if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom - DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n", - (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); - (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID); - // Called by Window.java: CloseWindow(); - num_events = 0; // end loop in case of destroyed display - } - break; - - case FocusIn: - DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); - break; - - case FocusOut: - DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); - (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); - break; - - case Expose: - DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); - - if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { - (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); - } - break; - - case MapNotify: - DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n", - (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect, - evt.xmap.event!=evt.xmap.window); - if( evt.xmap.event == evt.xmap.window ) { - // ignore child window notification - { - // update insets - int left, right, top, bottom; - NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); - } - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); - } - break; - - case UnmapNotify: - DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n", - (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure, - evt.xunmap.event!=evt.xunmap.window); - if( evt.xunmap.event == evt.xunmap.window ) { - // ignore child window notification - (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); - } - break; - - case ReparentNotify: - { - jlong parentResult; // 0 if root, otherwise proper value - Window winRoot, winTopParent; - #ifdef VERBOSE_ON - Window oldParentRoot, oldParentTopParent; - Window parentRoot, parentTopParent; - if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) { - oldParentRoot=0; oldParentTopParent = 0; - } - if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) { - parentRoot=0; parentTopParent = 0; - } - #endif - if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) { - winRoot=0; winTopParent = 0; - } - if(evt.xreparent.parent == winRoot) { - parentResult = 0; // our java indicator for root window - } else { - parentResult = (jlong) (intptr_t) evt.xreparent.parent; - } - #ifdef VERBOSE_ON - DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n", - evt.xreparent.x, evt.xreparent.y, - (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent, - (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, - (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); - #endif - (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); - } - break; - - // unhandled events .. yet .. - - default: - DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window); - } - } -} - - -/** - * Screen - */ - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: GetScreen - * Signature: (JI)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Screen_GetScreen0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_index) -{ - Display * dpy = (Display *)(intptr_t)display; - Screen * scrn= NULL; - - DBG_PRINT("X11: X11Screen_GetScreen0 dpy %p START\n", dpy); - - if(dpy==NULL) { - NewtCommon_FatalError(env, "invalid display connection.."); - } - - scrn = ScreenOfDisplay(dpy, screen_index); - if(scrn==NULL) { - fprintf(stderr, "couldn't get screen idx %d\n", screen_index); - } - DBG_PRINT("X11: X11Screen_GetScreen0 idx %d -> scrn %p DONE\n", screen_index, scrn); - return (jlong) (intptr_t) scrn; -} - -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getWidth0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display * dpy = (Display *) (intptr_t) display; - return (jint) XDisplayWidth( dpy, scrn_idx); -} - -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getHeight0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display * dpy = (Display *) (intptr_t) display; - return (jint) XDisplayHeight( dpy, scrn_idx); -} - - -static Bool NewtScreen_getRANDRVersion(Display *dpy, int *major, int *minor) { - if( 0 == XRRQueryVersion(dpy, major, minor) ) { - return False; - } - return True; -} - -static Bool NewtScreen_hasRANDR(Display *dpy) { - int major, minor; - return NewtScreen_getRANDRVersion(dpy, &major, &minor); -} - -static int NewtScreen_XRotation2Degree(JNIEnv *env, int xrotation) { - int rot; - if(xrotation == RR_Rotate_0) { - rot = 0; - } - else if(xrotation == RR_Rotate_90) { - rot = 90; - } - else if(xrotation == RR_Rotate_180) { - rot = 180; - } - else if(xrotation == RR_Rotate_270) { - rot = 270; - } else { - NewtCommon_throwNewRuntimeException(env, "invalid native rotation: %d", xrotation); - } - return rot; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getAvailableScreenModeRotations0 - * Signature: (JI)I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getAvailableScreenModeRotations0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - int num_rotations = 0; - Rotation cur_rotation, rotations_supported; - int rotations[4]; - int major, minor; - - if(False == NewtScreen_getRANDRVersion(dpy, &major, &minor)) { - fprintf(stderr, "RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - rotations_supported = XRRRotations (dpy, (int)scrn_idx, &cur_rotation); - - if(0 != (rotations_supported & RR_Rotate_0)) { - rotations[num_rotations++] = 0; - } - if(0 != (rotations_supported & RR_Rotate_90)) { - rotations[num_rotations++] = 90; - } - if(0 != (rotations_supported & RR_Rotate_180)) { - rotations[num_rotations++] = 180; - } - if(0 != (rotations_supported & RR_Rotate_270)) { - rotations[num_rotations++] = 270; - } - - jintArray properties = NULL; - - if(num_rotations>0) { - properties = (*env)->NewIntArray(env, num_rotations); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rotations); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, num_rotations, rotations); - } - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getNumScreenModeResolution0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getNumScreenModeResolutions0: RANDR not available\n"); - return 0; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - DBG_PRINT("getNumScreenModeResolutions0: %d\n", num_sizes); - - return num_sizes; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getScreenModeResolutions0 - * Signature: (JII)[I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeResolution0: RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - // Fill the properties in temp jint array - int propIndex = 0; - jint prop[4]; - - prop[propIndex++] = xrrs[(int)resMode_idx].width; - prop[propIndex++] = xrrs[(int)resMode_idx].height; - prop[propIndex++] = xrrs[(int)resMode_idx].mwidth; - prop[propIndex++] = xrrs[(int)resMode_idx].mheight; - - jintArray properties = (*env)->NewIntArray(env, 4); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", 4); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, 4, prop); - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getScreenModeRates0 - * Signature: (JII)[I - */ -JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx, jint resMode_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getScreenModeRates0: RANDR not available\n"); - return (*env)->NewIntArray(env, 0); - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)scrn_idx, &num_sizes); //get possible screen resolutions - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - int num_rates; - short *rates = XRRRates(dpy, (int)scrn_idx, (int)resMode_idx, &num_rates); - - jint prop[num_rates]; - int i; - for(i=0; i<num_rates; i++) { - prop[i] = (int) rates[i]; - /** fprintf(stderr, "rate[%d, %d, %d/%d]: %d\n", (int)scrn_idx, resMode_idx, i, num_rates, prop[i]); */ - } - - jintArray properties = (*env)->NewIntArray(env, num_rates); - if (properties == NULL) { - NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", num_rates); - } - - // move from the temp structure to the java structure - (*env)->SetIntArrayRegion(env, properties, 0, num_rates, prop); - - return properties; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenRate0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRate0: RANDR not available\n"); - return -1; - } - - // get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); - - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenRate0: %d\n", (int)original_rate); - - return (jint) original_rate; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenRotation0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenRotation0: RANDR not available\n"); - return -1; - } - - //get current resolutions and frequencies - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - - Rotation rotation; - XRRConfigCurrentConfiguration(conf, &rotation); - - //free - XRRFreeScreenConfigInfo(conf); - - return NewtScreen_XRotation2Degree(env, rotation); -} - - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: getCurrentScreenResolutionIndex0 - * Signature: (JI)I - */ -JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0 - (JNIEnv *env, jclass clazz, jlong display, jint scrn_idx) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)scrn_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_getCurrentScreenResolutionIndex0: RANDR not available\n"); - return -1; - } - - // get current resolutions and frequency configuration - XRRScreenConfiguration *conf = XRRGetScreenInfo(dpy, root); - short original_rate = XRRConfigCurrentRate(conf); - - Rotation original_rotation; - SizeID original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation); - - //free - XRRFreeScreenConfigInfo(conf); - - DBG_PRINT("getCurrentScreenResolutionIndex0: %d\n", (int)original_size_id); - return (jint)original_size_id; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: setCurrentScreenModeStart0 - * Signature: (JIIII)Z - */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) -{ - Display *dpy = (Display *) (intptr_t) display; - Window root = RootWindow(dpy, (int)screen_idx); - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModeStart0: RANDR not available\n"); - return JNI_FALSE; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - int rot; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - conf = XRRGetScreenInfo(dpy, root); - - switch(rotation) { - case 0: - rot = RR_Rotate_0; - break; - case 90: - rot = RR_Rotate_90; - break; - case 180: - rot = RR_Rotate_180; - break; - case 270: - rot = RR_Rotate_270; - break; - default: - NewtCommon_throwNewRuntimeException(env, "Invalid rotation: %d", rotation); - } - - DBG_PRINT("X11Screen.setCurrentScreenMode0: CHANGED TO %d: %d x %d PIXELS, %d Hz, %d degree\n", - resMode_idx, xrrs[resMode_idx].width, xrrs[resMode_idx].height, (int)freq, rotation); - - XRRSelectInput (dpy, root, RRScreenChangeNotifyMask); - - XSync(dpy, False); - XRRSetScreenConfigAndRate(dpy, conf, root, (int)resMode_idx, rot, (short)freq, CurrentTime); - XSync(dpy, False); - - //free - XRRFreeScreenConfigInfo(conf); - XSync(dpy, False); - - return JNI_TRUE; -} - -/* - * Class: jogamp_newt_driver_x11_X11Screen - * Method: setCurrentScreenModePollEnd0 - * Signature: (J)Z - */ -JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0 - (JNIEnv *env, jclass clazz, jlong display, jint screen_idx, jint resMode_idx, jint freq, jint rotation) -{ - Display *dpy = (Display *) (intptr_t) display; - int randr_event_base, randr_error_base; - XEvent evt; - XRRScreenChangeNotifyEvent * scn_event = (XRRScreenChangeNotifyEvent *) &evt; - - if(False == NewtScreen_hasRANDR(dpy)) { - DBG_PRINT("Java_jogamp_newt_driver_x11_X11Screen_setCurrentScreenModePollEnd0: RANDR not available\n"); - return JNI_FALSE; - } - - int num_sizes; - XRRScreenSize *xrrs = XRRSizes(dpy, (int)screen_idx, &num_sizes); //get possible screen resolutions - XRRScreenConfiguration *conf; - - if( 0 > resMode_idx || resMode_idx >= num_sizes ) { - NewtCommon_throwNewRuntimeException(env, "Invalid resolution index: ! 0 < %d < %d", resMode_idx, num_sizes); - } - - XRRQueryExtension(dpy, &randr_event_base, &randr_error_base); - - int done = 0; - int rot; - do { - if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { - return; - } - XNextEvent(dpy, &evt); - - switch (evt.type - randr_event_base) { - case RRScreenChangeNotify: - rot = NewtScreen_XRotation2Degree(env, (int)scn_event->rotation); - DBG_PRINT( "XRANDR: event . RRScreenChangeNotify call %p (root %p) resIdx %d rot %d %dx%d\n", - (void*)scn_event->window, (void*)scn_event->root, - (int)scn_event->size_index, rot, - scn_event->width, scn_event->height); - // done = scn_event->size_index == resMode_idx; // not reliable .. - done = rot == rotation && - scn_event->width == xrrs[resMode_idx].width && - scn_event->height == xrrs[resMode_idx].height; - break; - default: - DBG_PRINT("RANDR: event . unhandled %d 0x%X call %p\n", (int)evt.type, (int)evt.type, (void*)evt.xany.window); - } - XRRUpdateConfiguration(&evt); - } while(!done); - - XSync(dpy, False); - -} - /** * Window */ @@ -1468,37 +442,6 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Screen_setCurrentScree JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_initIDs0 (JNIEnv *env, jclass clazz) { - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); - positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); - reparentNotifyID = (*env)->GetMethodID(env, clazz, "reparentNotify", "(J)V"); - windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZIIIIII)V"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZIIIC)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); - enqueueRequestFocusID = (*env)->GetMethodID(env, clazz, "enqueueRequestFocus", "(Z)V"); - focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); - - if (insetsChangedID == NULL || - sizeChangedID == NULL || - positionChangedID == NULL || - focusChangedID == NULL || - visibleChangedID == NULL || - reparentNotifyID == NULL || - windowDestroyNotifyID == NULL || - windowRepaintID == NULL || - enqueueMouseEventID == NULL || - sendMouseEventID == NULL || - enqueueKeyEventID == NULL || - sendKeyEventID == NULL || - focusActionID == NULL || - enqueueRequestFocusID == NULL) { - return JNI_FALSE; - } return JNI_TRUE; } @@ -1513,14 +456,12 @@ static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) { static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) { if(width>0 && height>0 || x>=0 && y>=0) { // resize/position if requested XWindowChanges xwc; - int flags = 0; + int flags = CWX | CWY; memset(&xwc, 0, sizeof(XWindowChanges)); - if(0<=x && 0<=y) { - flags |= CWX | CWY; - xwc.x=x; - xwc.y=y; - } + xwc.x=x; + xwc.y=y; + if(0<width && 0<height) { flags |= CWWidth | CWHeight; xwc.width=width; @@ -1534,13 +475,12 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint /* * Class: jogamp_newt_driver_x11_X11Window * Method: CreateWindow - * Signature: (JJIJIIII)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, jlong visualID, jlong javaObjectAtom, jlong windowDeleteAtom, - jint x, jint y, jint width, jint height, int flags) + jint x, jint y, jint width, jint height, jboolean autoPosition, int flags) { Display * dpy = (Display *)(intptr_t)display; Atom wm_delete_atom = (Atom)windowDeleteAtom; @@ -1576,9 +516,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 if(0==windowParent) { windowParent = root; } - DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d, alwaysOnTop %d\n", + DBG_PRINT( "X11: CreateWindow dpy %p, parent %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", (void*)dpy, (void*)windowParent, x, y, width, height, - TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags)); + TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -1628,7 +568,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 { int _x = x, _y = y; // pos for CreateWindow, might be tweaked - if(0>_x || 0>_y) { + if(JNI_TRUE == autoPosition) { // user didn't requested specific position, use WM default _x = 0; _y = 0; @@ -1662,7 +602,6 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 { XEvent event; int left, right, top, bottom; - Bool userPos = 0<=x && 0<=y ; XMapWindow(dpy, window); XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values @@ -1671,19 +610,17 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom); (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); - if(!userPos) { + if(JNI_TRUE == autoPosition) { // get position from WM int dest_x, dest_y; Window child; XTranslateCoordinates(dpy, window, windowParent, 0, 0, &dest_x, &dest_y, &child); x = (int)dest_x; y = (int)dest_y; } - DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (is user-pos %d)\n", x, y, width, height, userPos); + DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition); x -= left; // top-level y -= top; // top-level - if(0>x) { x = 0; } - if(0>y) { y = 0; } DBG_PRINT("X11: [CreateWindow]: top-level: %d/%d\n", x, y); NewtWindows_setPosSize(dpy, window, x, y, width, height); @@ -1774,7 +711,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 fsEWMHFlags |= _NET_WM_ABOVE; // toggle above only } - displayDispatchErrorHandlerEnable(1, env); + NewtDisplay_displayDispatchErrorHandlerEnable(1, env); DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n", (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w, @@ -1792,7 +729,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) { Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ; if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) { - displayDispatchErrorHandlerEnable(0, env); + NewtDisplay_displayDispatchErrorHandlerEnable(0, env); return; } } @@ -1856,7 +793,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0 NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True); } - displayDispatchErrorHandlerEnable(0, env); + NewtDisplay_displayDispatchErrorHandlerEnable(0, env); DBG_PRINT( "X11: reconfigureWindow0 X\n"); } |