diff options
author | Kenneth Russel <[email protected]> | 2009-06-15 22:57:38 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2009-06-15 22:57:38 +0000 |
commit | a959c53b7ac91e489bf0959391e892790b9ff248 (patch) | |
tree | 4664742a4f9f6daa694364292e376ad2e6ee97d1 /src/newt | |
parent | 506b634b780dcd23aa61015c2ceba3e687196abf (diff) |
Copied JOGL_2_SANDBOX r1957 on to trunk; JOGL_2_SANDBOX branch is now closed
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1959 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/newt')
43 files changed, 9252 insertions, 0 deletions
diff --git a/src/newt/classes/com/sun/javafx/newt/Display.java b/src/newt/classes/com/sun/javafx/newt/Display.java new file mode 100755 index 000000000..b5d3c8520 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/Display.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +import javax.media.nativewindow.*; + +public abstract class Display { + + private static Class getDisplayClass(String type) + throws ClassNotFoundException + { + Class displayClass = null; + if (NativeWindowFactory.TYPE_EGL.equals(type)) { + displayClass = Class.forName("com.sun.javafx.newt.opengl.kd.KDDisplay"); + } else if (NativeWindowFactory.TYPE_WINDOWS.equals(type)) { + displayClass = Class.forName("com.sun.javafx.newt.windows.WindowsDisplay"); + } else if (NativeWindowFactory.TYPE_MACOSX.equals(type)) { + displayClass = Class.forName("com.sun.javafx.newt.macosx.MacDisplay"); + } else if (NativeWindowFactory.TYPE_X11.equals(type)) { + displayClass = Class.forName("com.sun.javafx.newt.x11.X11Display"); + } else if (NativeWindowFactory.TYPE_AWT.equals(type)) { + displayClass = Class.forName("com.sun.javafx.newt.awt.AWTDisplay"); + } else { + throw new RuntimeException("Unknown display type \"" + type + "\""); + } + return displayClass; + } + + protected static Display create(String type, String name) { + try { + Class displayClass = getDisplayClass(type); + Display display = (Display) displayClass.newInstance(); + display.name=name; + display.createNative(); + if(null==display.aDevice) { + throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); + } + return display; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public synchronized void destroy() { + closeNative(); + } + + protected static Display wrapHandle(String type, String name, AbstractGraphicsDevice aDevice) { + try { + Class displayClass = getDisplayClass(type); + Display display = (Display) displayClass.newInstance(); + display.name=name; + display.aDevice=aDevice; + return display; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected abstract void createNative(); + protected abstract void closeNative(); + + public String getName() { + return name; + } + + public long getHandle() { + return aDevice.getHandle(); + } + + public AbstractGraphicsDevice getGraphicsDevice() { + return aDevice; + } + + protected String name; + protected AbstractGraphicsDevice aDevice; +} + diff --git a/src/newt/classes/com/sun/javafx/newt/Event.java b/src/newt/classes/com/sun/javafx/newt/Event.java new file mode 100644 index 000000000..7d2b24ba5 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/Event.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public class Event { + private boolean isSystemEvent; + private int eventType; + private Window source; + private long when; + + Event(boolean isSystemEvent, int eventType, Window source, long when) { + this.isSystemEvent = isSystemEvent; + this.eventType = eventType; + this.source = source; + this.when = when; + } + + protected Event(int eventType, Window source, long when) { + this(false, eventType, source, when); + } + + /** Indicates whether this event was produced by the system or + generated by user code. */ + public final boolean isSystemEvent() { + return isSystemEvent; + } + + /** Returns the event type of this event. */ + public final int getEventType() { + return eventType; + } + + /** Returns the source Window which produced this Event. */ + public final Window getSource() { + return source; + } + + /** Returns the timestamp, in milliseconds, of this event. */ + public final long getWhen() { + return when; + } + + public String toString() { + return "Event[sys:"+isSystemEvent()+", source:"+getSource()+", when:"+getWhen()+"]"; + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/EventListener.java b/src/newt/classes/com/sun/javafx/newt/EventListener.java new file mode 100644 index 000000000..2af63bd7c --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/EventListener.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public interface EventListener +{ + public static final int WINDOW = 1 << 0; + public static final int MOUSE = 1 << 1; + public static final int KEY = 1 << 2; + +} + diff --git a/src/newt/classes/com/sun/javafx/newt/InputEvent.java b/src/newt/classes/com/sun/javafx/newt/InputEvent.java new file mode 100644 index 000000000..b49c72e75 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/InputEvent.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public abstract class InputEvent extends Event +{ + public static final int SHIFT_MASK = 1 << 0; + public static final int CTRL_MASK = 1 << 1; + public static final int META_MASK = 1 << 2; + public static final int ALT_MASK = 1 << 3; + public static final int ALT_GRAPH_MASK = 1 << 5; + public static final int BUTTON1_MASK = 1 << 6; + public static final int BUTTON2_MASK = 1 << 7; + public static final int BUTTON3_MASK = 1 << 8; + + protected InputEvent(boolean sysEvent, int eventType, Window source, long when, int modifiers) { + super(sysEvent, eventType, source, when); + this.consumed=false; + this.modifiers=modifiers; + } + + public void consume() { + consumed=true; + } + + public boolean isConsumed() { + return consumed; + } + public int getModifiers() { + return modifiers; + } + public boolean isAltDown() { + return (modifiers&ALT_MASK)!=0; + } + public boolean isAltGraphDown() { + return (modifiers&ALT_GRAPH_MASK)!=0; + } + public boolean isControlDown() { + return (modifiers&CTRL_MASK)!=0; + } + public boolean isMetaDown() { + return (modifiers&META_MASK)!=0; + } + public boolean isShiftDown() { + return (modifiers&SHIFT_MASK)!=0; + } + + public boolean isButton1Down() { + return (modifiers&BUTTON1_MASK)!=0; + } + + public boolean isButton2Down() { + return (modifiers&BUTTON2_MASK)!=0; + } + + public boolean isButton3Down() { + return (modifiers&BUTTON3_MASK)!=0; + } + + public String toString() { + return "InputEvent[modifiers:"+modifiers+"]"; + } + + private boolean consumed; + private int modifiers; +} diff --git a/src/newt/classes/com/sun/javafx/newt/KeyEvent.java b/src/newt/classes/com/sun/javafx/newt/KeyEvent.java new file mode 100644 index 000000000..7e224dbad --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/KeyEvent.java @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public class KeyEvent extends InputEvent +{ + KeyEvent(boolean sysEvent, int eventType, Window source, long when, int modifiers, int keyCode, char keyChar) { + super(sysEvent, eventType, source, when, modifiers); + this.keyCode=keyCode; + this.keyChar=keyChar; + } + public KeyEvent(int eventType, Window source, long when, int modifiers, int keyCode, char keyChar) { + this(false, eventType, source, when, modifiers, keyCode, keyChar); + } + + public char getKeyChar() { + return keyChar; + } + public int getKeyCode() { + return keyCode; + } + + public String toString() { + return "KeyEvent["+getEventTypeString(getEventType())+ + ", code "+keyCode+"(0x"+Integer.toHexString(keyCode)+"), char <"+keyChar+"> (0x"+Integer.toHexString((int)keyChar)+"), isActionKey "+isActionKey()+", "+super.toString()+"]"; + } + + public static String getEventTypeString(int type) { + switch(type) { + case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED"; + case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED"; + case EVENT_KEY_TYPED: return "EVENT_KEY_TYPED"; + default: return "unknown (" + type + ")"; + } + } + + public boolean isActionKey() { + switch (keyCode) { + case VK_HOME: + case VK_END: + case VK_PAGE_UP: + case VK_PAGE_DOWN: + case VK_UP: + case VK_DOWN: + case VK_LEFT: + case VK_RIGHT: + + case VK_F1: + case VK_F2: + case VK_F3: + case VK_F4: + case VK_F5: + case VK_F6: + case VK_F7: + case VK_F8: + case VK_F9: + case VK_F10: + case VK_F11: + case VK_F12: + case VK_F13: + case VK_F14: + case VK_F15: + case VK_F16: + case VK_F17: + case VK_F18: + case VK_F19: + case VK_F20: + case VK_F21: + case VK_F22: + case VK_F23: + case VK_F24: + case VK_PRINTSCREEN: + case VK_CAPS_LOCK: + case VK_PAUSE: + case VK_INSERT: + + case VK_HELP: + case VK_WINDOWS: + return true; + } + return false; + } + + private int keyCode; + private char keyChar; + + public static final int EVENT_KEY_PRESSED = 300; + public static final int EVENT_KEY_RELEASED= 301; + public static final int EVENT_KEY_TYPED = 302; + + /* Virtual key codes. */ + + public static final int VK_ENTER = '\n'; + public static final int VK_BACK_SPACE = '\b'; + public static final int VK_TAB = '\t'; + public static final int VK_CANCEL = 0x03; + public static final int VK_CLEAR = 0x0C; + public static final int VK_SHIFT = 0x10; + public static final int VK_CONTROL = 0x11; + public static final int VK_ALT = 0x12; + public static final int VK_PAUSE = 0x13; + public static final int VK_CAPS_LOCK = 0x14; + public static final int VK_ESCAPE = 0x1B; + public static final int VK_SPACE = 0x20; + public static final int VK_PAGE_UP = 0x21; + public static final int VK_PAGE_DOWN = 0x22; + public static final int VK_END = 0x23; + public static final int VK_HOME = 0x24; + + /** + * Constant for the non-numpad <b>left</b> arrow key. + * @see #VK_KP_LEFT + */ + public static final int VK_LEFT = 0x25; + + /** + * Constant for the non-numpad <b>up</b> arrow key. + * @see #VK_KP_UP + */ + public static final int VK_UP = 0x26; + + /** + * Constant for the non-numpad <b>right</b> arrow key. + * @see #VK_KP_RIGHT + */ + public static final int VK_RIGHT = 0x27; + + /** + * Constant for the non-numpad <b>down</b> arrow key. + * @see #VK_KP_DOWN + */ + public static final int VK_DOWN = 0x28; + + /** + * Constant for the comma key, "," + */ + public static final int VK_COMMA = 0x2C; + + /** + * Constant for the minus key, "-" + * @since 1.2 + */ + public static final int VK_MINUS = 0x2D; + + /** + * Constant for the period key, "." + */ + public static final int VK_PERIOD = 0x2E; + + /** + * Constant for the forward slash key, "/" + */ + public static final int VK_SLASH = 0x2F; + + /** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ + public static final int VK_0 = 0x30; + public static final int VK_1 = 0x31; + public static final int VK_2 = 0x32; + public static final int VK_3 = 0x33; + public static final int VK_4 = 0x34; + public static final int VK_5 = 0x35; + public static final int VK_6 = 0x36; + public static final int VK_7 = 0x37; + public static final int VK_8 = 0x38; + public static final int VK_9 = 0x39; + + /** + * Constant for the semicolon key, ";" + */ + public static final int VK_SEMICOLON = 0x3B; + + /** + * Constant for the equals key, "=" + */ + public static final int VK_EQUALS = 0x3D; + + /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ + public static final int VK_A = 0x41; + public static final int VK_B = 0x42; + public static final int VK_C = 0x43; + public static final int VK_D = 0x44; + public static final int VK_E = 0x45; + public static final int VK_F = 0x46; + public static final int VK_G = 0x47; + public static final int VK_H = 0x48; + public static final int VK_I = 0x49; + public static final int VK_J = 0x4A; + public static final int VK_K = 0x4B; + public static final int VK_L = 0x4C; + public static final int VK_M = 0x4D; + public static final int VK_N = 0x4E; + public static final int VK_O = 0x4F; + public static final int VK_P = 0x50; + public static final int VK_Q = 0x51; + public static final int VK_R = 0x52; + public static final int VK_S = 0x53; + public static final int VK_T = 0x54; + public static final int VK_U = 0x55; + public static final int VK_V = 0x56; + public static final int VK_W = 0x57; + public static final int VK_X = 0x58; + public static final int VK_Y = 0x59; + public static final int VK_Z = 0x5A; + + /** + * Constant for the open bracket key, "[" + */ + public static final int VK_OPEN_BRACKET = 0x5B; + + /** + * Constant for the back slash key, "\" + */ + public static final int VK_BACK_SLASH = 0x5C; + + /** + * Constant for the close bracket key, "]" + */ + public static final int VK_CLOSE_BRACKET = 0x5D; + + public static final int VK_NUMPAD0 = 0x60; + public static final int VK_NUMPAD1 = 0x61; + public static final int VK_NUMPAD2 = 0x62; + public static final int VK_NUMPAD3 = 0x63; + public static final int VK_NUMPAD4 = 0x64; + public static final int VK_NUMPAD5 = 0x65; + public static final int VK_NUMPAD6 = 0x66; + public static final int VK_NUMPAD7 = 0x67; + public static final int VK_NUMPAD8 = 0x68; + public static final int VK_NUMPAD9 = 0x69; + public static final int VK_MULTIPLY = 0x6A; + public static final int VK_ADD = 0x6B; + + /** + * This constant is obsolete, and is included only for backwards + * compatibility. + * @see #VK_SEPARATOR + */ + public static final int VK_SEPARATER = 0x6C; + + /** + * Constant for the Numpad Separator key. + * @since 1.4 + */ + public static final int VK_SEPARATOR = VK_SEPARATER; + + public static final int VK_SUBTRACT = 0x6D; + public static final int VK_DECIMAL = 0x6E; + public static final int VK_DIVIDE = 0x6F; + public static final int VK_DELETE = 0x7F; /* ASCII DEL */ + public static final int VK_NUM_LOCK = 0x90; + public static final int VK_SCROLL_LOCK = 0x91; + + /** Constant for the F1 function key. */ + public static final int VK_F1 = 0x70; + + /** Constant for the F2 function key. */ + public static final int VK_F2 = 0x71; + + /** Constant for the F3 function key. */ + public static final int VK_F3 = 0x72; + + /** Constant for the F4 function key. */ + public static final int VK_F4 = 0x73; + + /** Constant for the F5 function key. */ + public static final int VK_F5 = 0x74; + + /** Constant for the F6 function key. */ + public static final int VK_F6 = 0x75; + + /** Constant for the F7 function key. */ + public static final int VK_F7 = 0x76; + + /** Constant for the F8 function key. */ + public static final int VK_F8 = 0x77; + + /** Constant for the F9 function key. */ + public static final int VK_F9 = 0x78; + + /** Constant for the F10 function key. */ + public static final int VK_F10 = 0x79; + + /** Constant for the F11 function key. */ + public static final int VK_F11 = 0x7A; + + /** Constant for the F12 function key. */ + public static final int VK_F12 = 0x7B; + + /** + * Constant for the F13 function key. + * @since 1.2 + */ + /* F13 - F24 are used on IBM 3270 keyboard; use random range for constants. */ + public static final int VK_F13 = 0xF000; + + /** + * Constant for the F14 function key. + * @since 1.2 + */ + public static final int VK_F14 = 0xF001; + + /** + * Constant for the F15 function key. + * @since 1.2 + */ + public static final int VK_F15 = 0xF002; + + /** + * Constant for the F16 function key. + * @since 1.2 + */ + public static final int VK_F16 = 0xF003; + + /** + * Constant for the F17 function key. + * @since 1.2 + */ + public static final int VK_F17 = 0xF004; + + /** + * Constant for the F18 function key. + * @since 1.2 + */ + public static final int VK_F18 = 0xF005; + + /** + * Constant for the F19 function key. + * @since 1.2 + */ + public static final int VK_F19 = 0xF006; + + /** + * Constant for the F20 function key. + * @since 1.2 + */ + public static final int VK_F20 = 0xF007; + + /** + * Constant for the F21 function key. + * @since 1.2 + */ + public static final int VK_F21 = 0xF008; + + /** + * Constant for the F22 function key. + * @since 1.2 + */ + public static final int VK_F22 = 0xF009; + + /** + * Constant for the F23 function key. + * @since 1.2 + */ + public static final int VK_F23 = 0xF00A; + + /** + * Constant for the F24 function key. + * @since 1.2 + */ + public static final int VK_F24 = 0xF00B; + + public static final int VK_PRINTSCREEN = 0x9A; + public static final int VK_INSERT = 0x9B; + public static final int VK_HELP = 0x9C; + public static final int VK_META = 0x9D; + + public static final int VK_BACK_QUOTE = 0xC0; + public static final int VK_QUOTE = 0xDE; + + /** + * Constant for the numeric keypad <b>up</b> arrow key. + * @see #VK_UP + * @since 1.2 + */ + public static final int VK_KP_UP = 0xE0; + + /** + * Constant for the numeric keypad <b>down</b> arrow key. + * @see #VK_DOWN + * @since 1.2 + */ + public static final int VK_KP_DOWN = 0xE1; + + /** + * Constant for the numeric keypad <b>left</b> arrow key. + * @see #VK_LEFT + * @since 1.2 + */ + public static final int VK_KP_LEFT = 0xE2; + + /** + * Constant for the numeric keypad <b>right</b> arrow key. + * @see #VK_RIGHT + * @since 1.2 + */ + public static final int VK_KP_RIGHT = 0xE3; + + /* For European keyboards */ + /** @since 1.2 */ + public static final int VK_DEAD_GRAVE = 0x80; + /** @since 1.2 */ + public static final int VK_DEAD_ACUTE = 0x81; + /** @since 1.2 */ + public static final int VK_DEAD_CIRCUMFLEX = 0x82; + /** @since 1.2 */ + public static final int VK_DEAD_TILDE = 0x83; + /** @since 1.2 */ + public static final int VK_DEAD_MACRON = 0x84; + /** @since 1.2 */ + public static final int VK_DEAD_BREVE = 0x85; + /** @since 1.2 */ + public static final int VK_DEAD_ABOVEDOT = 0x86; + /** @since 1.2 */ + public static final int VK_DEAD_DIAERESIS = 0x87; + /** @since 1.2 */ + public static final int VK_DEAD_ABOVERING = 0x88; + /** @since 1.2 */ + public static final int VK_DEAD_DOUBLEACUTE = 0x89; + /** @since 1.2 */ + public static final int VK_DEAD_CARON = 0x8a; + /** @since 1.2 */ + public static final int VK_DEAD_CEDILLA = 0x8b; + /** @since 1.2 */ + public static final int VK_DEAD_OGONEK = 0x8c; + /** @since 1.2 */ + public static final int VK_DEAD_IOTA = 0x8d; + /** @since 1.2 */ + public static final int VK_DEAD_VOICED_SOUND = 0x8e; + /** @since 1.2 */ + public static final int VK_DEAD_SEMIVOICED_SOUND = 0x8f; + + /** @since 1.2 */ + public static final int VK_AMPERSAND = 0x96; + /** @since 1.2 */ + public static final int VK_ASTERISK = 0x97; + /** @since 1.2 */ + public static final int VK_QUOTEDBL = 0x98; + /** @since 1.2 */ + public static final int VK_LESS = 0x99; + + /** @since 1.2 */ + public static final int VK_GREATER = 0xa0; + /** @since 1.2 */ + public static final int VK_BRACELEFT = 0xa1; + /** @since 1.2 */ + public static final int VK_BRACERIGHT = 0xa2; + + /** + * Constant for the "@" key. + * @since 1.2 + */ + public static final int VK_AT = 0x0200; + + /** + * Constant for the ":" key. + * @since 1.2 + */ + public static final int VK_COLON = 0x0201; + + /** + * Constant for the "^" key. + * @since 1.2 + */ + public static final int VK_CIRCUMFLEX = 0x0202; + + /** + * Constant for the "$" key. + * @since 1.2 + */ + public static final int VK_DOLLAR = 0x0203; + + /** + * Constant for the Euro currency sign key. + * @since 1.2 + */ + public static final int VK_EURO_SIGN = 0x0204; + + /** + * Constant for the "!" key. + * @since 1.2 + */ + public static final int VK_EXCLAMATION_MARK = 0x0205; + + /** + * Constant for the inverted exclamation mark key. + * @since 1.2 + */ + public static final int VK_INVERTED_EXCLAMATION_MARK = 0x0206; + + /** + * Constant for the "(" key. + * @since 1.2 + */ + public static final int VK_LEFT_PARENTHESIS = 0x0207; + + /** + * Constant for the "#" key. + * @since 1.2 + */ + public static final int VK_NUMBER_SIGN = 0x0208; + + /** + * Constant for the "+" key. + * @since 1.2 + */ + public static final int VK_PLUS = 0x0209; + + /** + * Constant for the ")" key. + * @since 1.2 + */ + public static final int VK_RIGHT_PARENTHESIS = 0x020A; + + /** + * Constant for the "_" key. + * @since 1.2 + */ + public static final int VK_UNDERSCORE = 0x020B; + + /** + * Constant for the Microsoft Windows "Windows" key. + * It is used for both the left and right version of the key. + * @see #getKeyLocation() + * @since 1.5 + */ + public static final int VK_WINDOWS = 0x020C; + + /** + * Constant for the Microsoft Windows Context Menu key. + * @since 1.5 + */ + public static final int VK_CONTEXT_MENU = 0x020D; + + /* for input method support on Asian Keyboards */ + + /* not clear what this means - listed in Microsoft Windows API */ + public static final int VK_FINAL = 0x0018; + + /** Constant for the Convert function key. */ + /* Japanese PC 106 keyboard, Japanese Solaris keyboard: henkan */ + public static final int VK_CONVERT = 0x001C; + + /** Constant for the Don't Convert function key. */ + /* Japanese PC 106 keyboard: muhenkan */ + public static final int VK_NONCONVERT = 0x001D; + + /** Constant for the Accept or Commit function key. */ + /* Japanese Solaris keyboard: kakutei */ + public static final int VK_ACCEPT = 0x001E; + + /* not clear what this means - listed in Microsoft Windows API */ + public static final int VK_MODECHANGE = 0x001F; + + /* replaced by VK_KANA_LOCK for Microsoft Windows and Solaris; + might still be used on other platforms */ + public static final int VK_KANA = 0x0015; + + /* replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris; + might still be used for other platforms */ + public static final int VK_KANJI = 0x0019; + + /** + * Constant for the Alphanumeric function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: eisuu */ + public static final int VK_ALPHANUMERIC = 0x00F0; + + /** + * Constant for the Katakana function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: katakana */ + public static final int VK_KATAKANA = 0x00F1; + + /** + * Constant for the Hiragana function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: hiragana */ + public static final int VK_HIRAGANA = 0x00F2; + + /** + * Constant for the Full-Width Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: zenkaku */ + public static final int VK_FULL_WIDTH = 0x00F3; + + /** + * Constant for the Half-Width Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: hankaku */ + public static final int VK_HALF_WIDTH = 0x00F4; + + /** + * Constant for the Roman Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: roumaji */ + public static final int VK_ROMAN_CHARACTERS = 0x00F5; + + /** + * Constant for the All Candidates function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */ + public static final int VK_ALL_CANDIDATES = 0x0100; + + /** + * Constant for the Previous Candidate function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */ + public static final int VK_PREVIOUS_CANDIDATE = 0x0101; + + /** + * Constant for the Code Input function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */ + public static final int VK_CODE_INPUT = 0x0102; + + /** + * Constant for the Japanese-Katakana function key. + * This key switches to a Japanese input method and selects its Katakana input mode. + * @since 1.2 + */ + /* Japanese Macintosh keyboard - VK_JAPANESE_HIRAGANA + SHIFT */ + public static final int VK_JAPANESE_KATAKANA = 0x0103; + + /** + * Constant for the Japanese-Hiragana function key. + * This key switches to a Japanese input method and selects its Hiragana input mode. + * @since 1.2 + */ + /* Japanese Macintosh keyboard */ + public static final int VK_JAPANESE_HIRAGANA = 0x0104; + + /** + * Constant for the Japanese-Roman function key. + * This key switches to a Japanese input method and selects its Roman-Direct input mode. + * @since 1.2 + */ + /* Japanese Macintosh keyboard */ + public static final int VK_JAPANESE_ROMAN = 0x0105; + + /** + * Constant for the locking Kana function key. + * This key locks the keyboard into a Kana layout. + * @since 1.3 + */ + /* Japanese PC 106 keyboard with special Windows driver - eisuu + Control; Japanese Solaris keyboard: kana */ + public static final int VK_KANA_LOCK = 0x0106; + + /** + * Constant for the input method on/off key. + * @since 1.3 + */ + /* Japanese PC 106 keyboard: kanji. Japanese Solaris keyboard: nihongo */ + public static final int VK_INPUT_METHOD_ON_OFF = 0x0107; + + /* for Sun keyboards */ + /** @since 1.2 */ + public static final int VK_CUT = 0xFFD1; + /** @since 1.2 */ + public static final int VK_COPY = 0xFFCD; + /** @since 1.2 */ + public static final int VK_PASTE = 0xFFCF; + /** @since 1.2 */ + public static final int VK_UNDO = 0xFFCB; + /** @since 1.2 */ + public static final int VK_AGAIN = 0xFFC9; + /** @since 1.2 */ + public static final int VK_FIND = 0xFFD0; + /** @since 1.2 */ + public static final int VK_PROPS = 0xFFCA; + /** @since 1.2 */ + public static final int VK_STOP = 0xFFC8; + + /** + * Constant for the Compose function key. + * @since 1.2 + */ + public static final int VK_COMPOSE = 0xFF20; + + /** + * Constant for the AltGraph function key. + * @since 1.2 + */ + public static final int VK_ALT_GRAPH = 0xFF7E; + + /** + * Constant for the Begin key. + * @since 1.5 + */ + public static final int VK_BEGIN = 0xFF58; + + /** + * This value is used to indicate that the keyCode is unknown. + * KEY_TYPED events do not have a keyCode value; this value + * is used instead. + */ + public static final int VK_UNDEFINED = 0x0; +} + diff --git a/src/newt/classes/com/sun/javafx/newt/KeyListener.java b/src/newt/classes/com/sun/javafx/newt/KeyListener.java new file mode 100644 index 000000000..6f022c45a --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/KeyListener.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public interface KeyListener extends EventListener +{ + public void keyPressed(KeyEvent e); + public void keyReleased(KeyEvent e); + public void keyTyped(KeyEvent e) ; +} + diff --git a/src/newt/classes/com/sun/javafx/newt/MouseEvent.java b/src/newt/classes/com/sun/javafx/newt/MouseEvent.java new file mode 100644 index 000000000..ede193e1c --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/MouseEvent.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public class MouseEvent extends InputEvent +{ + public static final int BUTTON1 = 1; + public static final int BUTTON2 = 2; + public static final int BUTTON3 = 3; + public static final int BUTTON4 = 4; + public static final int BUTTON5 = 5; + public static final int BUTTON6 = 6; + public static final int BUTTON_NUMBER = 6; + + protected MouseEvent(boolean sysEvent, int eventType, Window source, long when, + int modifiers, int x, int y, int clickCount, int button, + int rotation) + { + super(sysEvent, eventType, source, when, modifiers); + this.x=x; + this.y=y; + this.clickCount=clickCount; + this.button=button; + this.wheelRotation = rotation; + } + public MouseEvent(int eventType, Window source, long when, int modifiers, + int x, int y, int clickCount, int button, int rotation) { + this(false, eventType, source, when, modifiers, x, y, clickCount, button, + rotation); + } + + public int getButton() { + return button; + } + public int getClickCount() { + return clickCount; + } + public int getX() { + return x; + } + public int getY() { + return y; + } + public int getWheelRotation() { + return wheelRotation; + } + + public String toString() { + return "MouseEvent["+getEventTypeString(getEventType())+ + ", "+x+"/"+y+", button "+button+", count "+clickCount+ + ", wheel rotation "+wheelRotation+ + ", "+super.toString()+"]"; + } + + public static String getEventTypeString(int type) { + switch(type) { + case EVENT_MOUSE_CLICKED: return "EVENT_MOUSE_CLICKED"; + case EVENT_MOUSE_ENTERED: return "EVENT_MOUSE_ENTERED"; + case EVENT_MOUSE_EXITED: return "EVENT_MOUSE_EXITED"; + case EVENT_MOUSE_PRESSED: return "EVENT_MOUSE_PRESSED"; + case EVENT_MOUSE_RELEASED: return "EVENT_MOUSE_RELEASED"; + case EVENT_MOUSE_MOVED: return "EVENT_MOUSE_MOVED"; + case EVENT_MOUSE_DRAGGED: return "EVENT_MOUSE_DRAGGED"; + case EVENT_MOUSE_WHEEL_MOVED: return "EVENT_MOUSE_WHEEL_MOVED"; + default: return "unknown (" + type + ")"; + } + } + + private int x, y, clickCount, button, wheelRotation; + + public static final int EVENT_MOUSE_CLICKED = 200; + public static final int EVENT_MOUSE_ENTERED = 201; + public static final int EVENT_MOUSE_EXITED = 202; + public static final int EVENT_MOUSE_PRESSED = 203; + public static final int EVENT_MOUSE_RELEASED = 204; + public static final int EVENT_MOUSE_MOVED = 205; + public static final int EVENT_MOUSE_DRAGGED = 206; + public static final int EVENT_MOUSE_WHEEL_MOVED = 207; +} diff --git a/src/newt/classes/com/sun/javafx/newt/MouseListener.java b/src/newt/classes/com/sun/javafx/newt/MouseListener.java new file mode 100644 index 000000000..3d2031f2a --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/MouseListener.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public interface MouseListener extends EventListener +{ + public void mouseClicked(MouseEvent e); + public void mouseEntered(MouseEvent e); + public void mouseExited(MouseEvent e); + public void mousePressed(MouseEvent e); + public void mouseReleased(MouseEvent e); + public void mouseMoved(MouseEvent e); + public void mouseDragged(MouseEvent e); + public void mouseWheelMoved(MouseEvent e); +} + diff --git a/src/newt/classes/com/sun/javafx/newt/NewtFactory.java b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java new file mode 100755 index 000000000..c9b230355 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/NewtFactory.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +import javax.media.nativewindow.*; +import java.util.ArrayList; +import java.util.Iterator; + +public abstract class NewtFactory { + // Work-around for initialization order problems on Mac OS X + // between native Newt and (apparently) Fmod + static { + Window.init(NativeWindowFactory.getNativeWindowType(true)); + } + + static int getPropertyIntValue(String propname) { + int i=0; + String s = System.getProperty(propname); + if(null!=s) { + try { + i = Integer.valueOf(s).intValue(); + } catch (NumberFormatException nfe) {} + } + return i; + } + + /** + * Create a Display entity, incl native creation + */ + public static Display createDisplay(String name) { + return Display.create(NativeWindowFactory.getNativeWindowType(true), name); + } + + /** + * Create a Display entity using the given implementation type, incl native creation + */ + public static Display createDisplay(String type, String name) { + return Display.create(type, name); + } + + /** + * Create a Screen entity, incl native creation + */ + public static Screen createScreen(Display display, int index) { + return Screen.create(NativeWindowFactory.getNativeWindowType(true), display, index); + } + + /** + * Create a Screen entity using the given implementation type, incl native creation + */ + public static Screen createScreen(String type, Display display, int index) { + return Screen.create(type, display, index); + } + + /** + * Create a Window entity, incl native creation + */ + public static Window createWindow(Screen screen, Capabilities caps) { + return Window.create(NativeWindowFactory.getNativeWindowType(true), screen, caps); + } + + public static Window createWindow(Screen screen, Capabilities caps, boolean undecorated) { + return Window.create(NativeWindowFactory.getNativeWindowType(true), screen, caps, undecorated); + } + + /** + * Create a Window entity using the given implementation type, incl native creation + */ + public static Window createWindow(String type, Screen screen, Capabilities caps) { + return Window.create(type, screen, caps); + } + + /** + * Instantiate a Display entity using the native handle. + */ + public static Display wrapDisplay(String name, AbstractGraphicsDevice device) { + return Display.wrapHandle(NativeWindowFactory.getNativeWindowType(true), name, device); + } + + /** + * Instantiate a Screen entity using the native handle. + */ + public static Screen wrapScreen(Display display, AbstractGraphicsScreen screen) { + return Screen.wrapHandle(NativeWindowFactory.getNativeWindowType(true), display, screen); + } + + /** + * Instantiate a Window entity using the native handle. + */ + public static Window wrapWindow(Screen screen, AbstractGraphicsConfiguration config, + long windowHandle, boolean fullscreen, boolean visible, + int x, int y, int width, int height) { + return Window.wrapHandle(NativeWindowFactory.getNativeWindowType(true), screen, config, + windowHandle, fullscreen, visible, x, y, width, height); + } + + private static final boolean instanceOf(Object obj, String clazzName) { + Class clazz = obj.getClass(); + do { + if(clazz.getName().equals(clazzName)) { + return true; + } + clazz = clazz.getSuperclass(); + } while (clazz!=null); + return false; + } + +} + diff --git a/src/newt/classes/com/sun/javafx/newt/Screen.java b/src/newt/classes/com/sun/javafx/newt/Screen.java new file mode 100755 index 000000000..346257f6c --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/Screen.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +import javax.media.nativewindow.*; + +public abstract class Screen { + + private static Class getScreenClass(String type) + throws ClassNotFoundException + { + Class screenClass = null; + if (NativeWindowFactory.TYPE_EGL.equals(type)) { + screenClass = Class.forName("com.sun.javafx.newt.opengl.kd.KDScreen"); + } else if (NativeWindowFactory.TYPE_WINDOWS.equals(type)) { + screenClass = Class.forName("com.sun.javafx.newt.windows.WindowsScreen"); + } else if (NativeWindowFactory.TYPE_MACOSX.equals(type)) { + screenClass = Class.forName("com.sun.javafx.newt.macosx.MacScreen"); + } else if (NativeWindowFactory.TYPE_X11.equals(type)) { + screenClass = Class.forName("com.sun.javafx.newt.x11.X11Screen"); + } else if (NativeWindowFactory.TYPE_AWT.equals(type)) { + screenClass = Class.forName("com.sun.javafx.newt.awt.AWTScreen"); + } else { + throw new RuntimeException("Unknown window type \"" + type + "\""); + } + return screenClass; + } + + protected static Screen create(String type, Display display, int idx) { + try { + if(usrWidth<0 || usrHeight<0) { + usrWidth = NewtFactory.getPropertyIntValue("newt.ws.swidth"); + usrHeight = NewtFactory.getPropertyIntValue("newt.ws.sheight"); + System.out.println("User screen size "+usrWidth+"x"+usrHeight); + } + Class screenClass = getScreenClass(type); + Screen screen = (Screen) screenClass.newInstance(); + screen.display = display; + screen.createNative(idx); + if(null==screen.aScreen) { + throw new RuntimeException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen"); + } + return screen; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public synchronized void destroy() { + closeNative(); + } + + protected static Screen wrapHandle(String type, Display display, AbstractGraphicsScreen aScreen) { + try { + Class screenClass = getScreenClass(type); + Screen screen = (Screen) screenClass.newInstance(); + screen.display = display; + screen.aScreen = aScreen; + return screen; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected abstract void createNative(int index); + protected abstract void closeNative(); + + protected void setScreenSize(int w, int h) { + System.out.println("Detected screen size "+w+"x"+h); + width=w; height=h; + } + + public Display getDisplay() { + return display; + } + + public int getIndex() { + return aScreen.getIndex(); + } + + public AbstractGraphicsScreen getGraphicsScreen() { + return aScreen; + } + + /** + * The actual implementation shall return the detected display value, + * if not we return 800. + * This can be overwritten with the user property 'newt.ws.swidth', + */ + public int getWidth() { + return (usrWidth>0) ? usrWidth : (width>0) ? width : 480; + } + + /** + * The actual implementation shall return the detected display value, + * if not we return 480. + * This can be overwritten with the user property 'newt.ws.sheight', + */ + public int getHeight() { + return (usrHeight>0) ? usrHeight : (height>0) ? height : 480; + } + + protected Display display; + protected AbstractGraphicsScreen aScreen; + 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 +} + diff --git a/src/newt/classes/com/sun/javafx/newt/Window.java b/src/newt/classes/com/sun/javafx/newt/Window.java new file mode 100755 index 000000000..68cb97834 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/Window.java @@ -0,0 +1,664 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +import com.sun.javafx.newt.impl.Debug; +import javax.media.nativewindow.*; + +import java.util.ArrayList; +import java.util.Iterator; + +public abstract class Window implements NativeWindow +{ + public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); + public static final boolean DEBUG_KEY_EVENT = Debug.debug("Window.KeyEvent"); + public static final boolean DEBUG_WINDOW_EVENT = Debug.debug("Window.WindowEvent"); + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + + // Workaround for initialization order problems on Mac OS X + // between native Newt and (apparently) Fmod -- if Fmod is + // initialized first then the connection to the window server + // breaks, leading to errors from deep within the AppKit + static void init(String type) { + if (NativeWindowFactory.TYPE_MACOSX.equals(type)) { + try { + getWindowClass(type); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private static Class getWindowClass(String type) + throws ClassNotFoundException + { + Class windowClass = null; + if (NativeWindowFactory.TYPE_EGL.equals(type)) { + windowClass = Class.forName("com.sun.javafx.newt.opengl.kd.KDWindow"); + } else if (NativeWindowFactory.TYPE_WINDOWS.equals(type)) { + windowClass = Class.forName("com.sun.javafx.newt.windows.WindowsWindow"); + } else if (NativeWindowFactory.TYPE_MACOSX.equals(type)) { + windowClass = Class.forName("com.sun.javafx.newt.macosx.MacWindow"); + } else if (NativeWindowFactory.TYPE_X11.equals(type)) { + windowClass = Class.forName("com.sun.javafx.newt.x11.X11Window"); + } else if (NativeWindowFactory.TYPE_AWT.equals(type)) { + windowClass = Class.forName("com.sun.javafx.newt.awt.AWTWindow"); + } else { + throw new NativeWindowException("Unknown window type \"" + type + "\""); + } + return windowClass; + } + + protected static Window create(String type, Screen screen, Capabilities caps) { + return create(type, screen, caps, false); + } + + protected static Window create(String type, Screen screen, Capabilities caps, boolean undecorated) { + try { + Class windowClass = getWindowClass(type); + Window window = (Window) windowClass.newInstance(); + window.invalidate(); + window.screen = screen; + window.setUndecorated(undecorated); + window.createNative(caps); + return window; + } catch (Throwable t) { + t.printStackTrace(); + throw new NativeWindowException(t); + } + } + + protected static Window wrapHandle(String type, Screen screen, AbstractGraphicsConfiguration config, + long windowHandle, boolean fullscreen, boolean visible, + int x, int y, int width, int height) + { + try { + Class windowClass = getWindowClass(type); + Window window = (Window) windowClass.newInstance(); + window.invalidate(); + window.screen = screen; + window.config = config; + window.windowHandle = windowHandle; + window.fullscreen=fullscreen; + window.visible=visible; + window.x=x; + window.y=y; + window.width=width; + window.height=height; + return window; + } catch (Throwable t) { + t.printStackTrace(); + throw new NativeWindowException(t); + } + } + + /** + * Create native windowHandle, ie creates a new native invisible window. + * + * Shall use the capabilities to determine the graphics configuration + * and shall set the chosen capabilities. + */ + protected abstract void createNative(Capabilities caps); + + protected abstract void closeNative(); + + public Screen getScreen() { + return screen; + } + + /** + * eventMask is a bitfield of EventListener event flags + */ + public void pumpMessages(int eventMask) { + if(this.eventMask!=eventMask && eventMask>0) { + this.eventMask=eventMask; + eventMask*=-1; + } + dispatchMessages(eventMask); + } + + public void pumpMessages() { + int em = 0; + if(windowListeners.size()>0) em |= EventListener.WINDOW; + if(mouseListeners.size()>0) em |= EventListener.MOUSE; + if(keyListeners.size()>0) em |= EventListener.KEY; + pumpMessages(em); + } + + protected abstract void dispatchMessages(int eventMask); + + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append("NEWT-Window[config "+config+ + ", windowHandle 0x"+Long.toHexString(getWindowHandle())+ + ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ + ", pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ + ", visible "+isVisible()+ + ", "+screen+ + ", wrappedWindow "+getWrappedWindow()); + + sb.append(", WindowListeners num "+windowListeners.size()+" ["); + for (Iterator iter = windowListeners.iterator(); iter.hasNext(); ) { + sb.append(iter.next()+", "); + } + sb.append("], MouseListeners num "+mouseListeners.size()+" ["); + for (Iterator iter = mouseListeners.iterator(); iter.hasNext(); ) { + sb.append(iter.next()+", "); + } + sb.append("], KeyListeners num "+keyListeners.size()+" ["); + for (Iterator iter = keyListeners.iterator(); iter.hasNext(); ) { + sb.append(iter.next()+", "); + } + sb.append("] ]"); + return sb.toString(); + } + + protected Screen screen; + + protected AbstractGraphicsConfiguration config; + protected long windowHandle; + protected Exception lockedStack = null; + protected boolean fullscreen, visible; + protected int width, height, x, y; + protected int eventMask; + + protected String title = "Newt Window"; + protected boolean undecorated = false; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setUndecorated(boolean value) { + undecorated = value; + } + + public boolean isUndecorated() { + return undecorated; + } + + public void requestFocus() { + } + + // + // NativeWindow impl + // + + public synchronized int lockSurface() throws NativeWindowException { + // We leave the ToolkitLock lock to the specializtion's discretion, + // ie the implicit JAWTWindow in case of AWTWindow + if (null!=lockedStack) { + lockedStack.printStackTrace(); + throw new NativeWindowException("NEWT Surface already locked - "+Thread.currentThread().getName()+" "+this); + } + + lockedStack = new Exception("NEWT Surface previously locked by "+Thread.currentThread().getName()); + return LOCK_SUCCESS; + } + + public synchronized void unlockSurface() { + if (null!=lockedStack) { + lockedStack = null; + } else { + throw new NativeWindowException("NEWT Surface not locked"); + } + // We leave the ToolkitLock unlock to the specializtion's discretion, + // ie the implicit JAWTWindow in case of AWTWindow + } + + public synchronized boolean isSurfaceLocked() { + return null!=lockedStack; + } + + public synchronized Exception getLockedStack() { + return lockedStack; + } + + public synchronized void destroy() { + if(DEBUG_WINDOW_EVENT) { + System.out.println("Window.destroy() start "+Thread.currentThread().getName()); + } + synchronized(windowListeners) { + windowListeners = new ArrayList(); + } + synchronized(mouseListeners) { + mouseListeners = new ArrayList(); + } + synchronized(keyListeners) { + keyListeners = new ArrayList(); + } + closeNative(); + invalidate(); + if(DEBUG_WINDOW_EVENT) { + System.out.println("Window.destroy() end "+Thread.currentThread().getName()); + } + } + + public void invalidate() { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread().getName()); + e.printStackTrace(); + } + screen = null; + windowHandle = 0; + fullscreen=false; + visible=false; + eventMask = 0; + + // Default position and dimension will be re-set immediately by user + width = 100; + height = 100; + x=0; + y=0; + } + + protected void clearEventMask() { + eventMask=0; + } + + public long getDisplayHandle() { + return screen.getDisplay().getHandle(); + } + + public int getScreenIndex() { + return screen.getIndex(); + } + + public long getWindowHandle() { + return windowHandle; + } + + public long getSurfaceHandle() { + return windowHandle; // default: return window handle + } + + /** Special method to dispose a surface handle, + in case of a device change _and_ where there + is a different semantics of window handle and surface handle. + This is currently only true for Windows. */ + public void disposeSurfaceHandle() { + } + + public AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + /** If this Window actually wraps one from another toolkit such as + the AWT, this will return a non-null value. */ + public Object getWrappedWindow() { + return null; + } + + // + // Additional methods + // + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public boolean isVisible() { + return visible; + } + + public boolean isFullscreen() { + return fullscreen; + } + + private boolean autoDrawableMember = false; + + /** If the implementation is capable of detecting a device change + return true and clear the status/reason of the change. */ + public boolean hasDeviceChanged() { + return false; + } + + /** + * If set to true, + * certain action will be performed by the owning + * AutoDrawable, ie the destroy() call within windowDestroyNotify() + */ + public void setAutoDrawableClient(boolean b) { + autoDrawableMember = b; + } + + protected void windowDestroyNotify() { + if(DEBUG_WINDOW_EVENT) { + System.out.println("Window.windowDestroyeNotify start "+Thread.currentThread().getName()); + } + + sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); + + if(!autoDrawableMember) { + destroy(); + } + + if(DEBUG_WINDOW_EVENT) { + System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread().getName()); + } + } + + protected void windowDestroyed() { + if(DEBUG_WINDOW_EVENT) { + System.out.println("Window.windowDestroyed "+Thread.currentThread().getName()); + } + invalidate(); + } + + public abstract void setVisible(boolean visible); + public abstract void setSize(int width, int height); + public abstract void setPosition(int x, int y); + public abstract boolean setFullscreen(boolean fullscreen); + + // + // MouseListener Support + // + + public void addMouseListener(MouseListener l) { + if(l == null) { + return; + } + synchronized(mouseListeners) { + ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); + newMouseListeners.add(l); + mouseListeners = newMouseListeners; + } + } + + public void removeMouseListener(MouseListener l) { + if (l == null) { + return; + } + synchronized(mouseListeners) { + ArrayList newMouseListeners = (ArrayList) mouseListeners.clone(); + newMouseListeners.remove(l); + mouseListeners = newMouseListeners; + } + } + + public MouseListener[] getMouseListeners() { + synchronized(mouseListeners) { + return (MouseListener[]) mouseListeners.toArray(); + } + } + + private ArrayList mouseListeners = new ArrayList(); + private int mouseButtonPressed = 0; // current pressed mouse button number + private long lastMousePressed = 0; // last time when a mouse button was pressed + private int lastMouseClickCount = 0; // last mouse button click count + public static final int ClickTimeout = 300; + + protected void sendMouseEvent(int eventType, int modifiers, + int x, int y, int button, int rotation) { + if(DEBUG_MOUSE_EVENT) { + System.out.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); + } + if(button<0||button>MouseEvent.BUTTON_NUMBER) { + throw new NativeWindowException("Invalid mouse button number" + button); + } + long when = System.currentTimeMillis(); + MouseEvent eClicked = null; + MouseEvent e = null; + + if(MouseEvent.EVENT_MOUSE_PRESSED==eventType) { + if(when-lastMousePressed<ClickTimeout) { + lastMouseClickCount++; + } else { + lastMouseClickCount=1; + } + lastMousePressed=when; + mouseButtonPressed=button; + e = new MouseEvent(true, eventType, this, when, + modifiers, x, y, lastMouseClickCount, button, 0); + } else if(MouseEvent.EVENT_MOUSE_RELEASED==eventType) { + e = new MouseEvent(true, eventType, this, when, + modifiers, x, y, lastMouseClickCount, button, 0); + if(when-lastMousePressed<ClickTimeout) { + eClicked = new MouseEvent(true, MouseEvent.EVENT_MOUSE_CLICKED, this, when, + modifiers, x, y, lastMouseClickCount, button, 0); + } else { + lastMouseClickCount=0; + lastMousePressed=0; + } + mouseButtonPressed=0; + } else if(MouseEvent.EVENT_MOUSE_MOVED==eventType) { + if (mouseButtonPressed>0) { + e = new MouseEvent(true, MouseEvent.EVENT_MOUSE_DRAGGED, this, when, + modifiers, x, y, 1, mouseButtonPressed, 0); + } else { + e = new MouseEvent(true, eventType, this, when, + modifiers, x, y, 0, button, 0); + } + } else if(MouseEvent.EVENT_MOUSE_WHEEL_MOVED==eventType) { + e = new MouseEvent(true, eventType, this, when, modifiers, x, y, 0, button, rotation); + } else { + e = new MouseEvent(true, eventType, this, when, modifiers, x, y, 0, button, 0); + } + + if(DEBUG_MOUSE_EVENT) { + System.out.println("sendMouseEvent: event: "+e); + if(null!=eClicked) { + System.out.println("sendMouseEvent: event Clicked: "+eClicked); + } + } + + ArrayList listeners = null; + synchronized(mouseListeners) { + listeners = mouseListeners; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + MouseListener l = (MouseListener) i.next(); + switch(e.getEventType()) { + case MouseEvent.EVENT_MOUSE_CLICKED: + l.mouseClicked(e); + break; + case MouseEvent.EVENT_MOUSE_ENTERED: + l.mouseEntered(e); + break; + case MouseEvent.EVENT_MOUSE_EXITED: + l.mouseExited(e); + break; + case MouseEvent.EVENT_MOUSE_PRESSED: + l.mousePressed(e); + break; + case MouseEvent.EVENT_MOUSE_RELEASED: + l.mouseReleased(e); + if(null!=eClicked) { + l.mouseClicked(eClicked); + } + break; + case MouseEvent.EVENT_MOUSE_MOVED: + l.mouseMoved(e); + break; + case MouseEvent.EVENT_MOUSE_DRAGGED: + l.mouseDragged(e); + break; + case MouseEvent.EVENT_MOUSE_WHEEL_MOVED: + l.mouseWheelMoved(e); + break; + default: + throw new NativeWindowException("Unexpected mouse event type " + e.getEventType()); + } + } + } + + // + // KeyListener Support + // + + public void addKeyListener(KeyListener l) { + if(l == null) { + return; + } + synchronized(keyListeners) { + ArrayList newKeyListeners = (ArrayList) keyListeners.clone(); + newKeyListeners.add(l); + keyListeners = newKeyListeners; + } + } + + public void removeKeyListener(KeyListener l) { + if (l == null) { + return; + } + synchronized(keyListeners) { + ArrayList newKeyListeners = (ArrayList) keyListeners.clone(); + newKeyListeners.remove(l); + keyListeners = newKeyListeners; + } + } + + public KeyListener[] getKeyListeners() { + synchronized(keyListeners) { + return (KeyListener[]) keyListeners.toArray(); + } + } + + private ArrayList keyListeners = new ArrayList(); + + protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + KeyEvent e = new KeyEvent(true, eventType, this, System.currentTimeMillis(), + modifiers, keyCode, keyChar); + if(DEBUG_KEY_EVENT) { + System.out.println("sendKeyEvent: "+e); + } + ArrayList listeners = null; + synchronized(keyListeners) { + listeners = keyListeners; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + KeyListener l = (KeyListener) i.next(); + switch(eventType) { + 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()); + } + } + } + + // + // WindowListener Support + // + + private ArrayList windowListeners = new ArrayList(); + + public void addWindowListener(WindowListener l) { + if(l == null) { + return; + } + synchronized(windowListeners) { + ArrayList newWindowListeners = (ArrayList) windowListeners.clone(); + newWindowListeners.add(l); + windowListeners = newWindowListeners; + } + } + + public void removeWindowListener(WindowListener l) { + if (l == null) { + return; + } + synchronized(windowListeners) { + ArrayList newWindowListeners = (ArrayList) windowListeners.clone(); + newWindowListeners.remove(l); + windowListeners = newWindowListeners; + } + } + + public WindowListener[] getWindowListeners() { + synchronized(windowListeners) { + return (WindowListener[]) windowListeners.toArray(); + } + } + + protected void sendWindowEvent(int eventType) { + WindowEvent e = new WindowEvent(true, eventType, this, System.currentTimeMillis()); + if(DEBUG_WINDOW_EVENT) { + System.out.println("sendWindowEvent: "+e); + } + ArrayList listeners = null; + synchronized(windowListeners) { + listeners = windowListeners; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + WindowListener l = (WindowListener) i.next(); + switch(eventType) { + case WindowEvent.EVENT_WINDOW_RESIZED: + l.windowResized(e); + break; + case WindowEvent.EVENT_WINDOW_MOVED: + l.windowMoved(e); + break; + case WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY: + l.windowDestroyNotify(e); + break; + case WindowEvent.EVENT_WINDOW_GAINED_FOCUS: + l.windowGainedFocus(e); + break; + case WindowEvent.EVENT_WINDOW_LOST_FOCUS: + l.windowLostFocus(e); + break; + default: + throw + new NativeWindowException("Unexpected window event type " + + e.getEventType()); + } + } + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/WindowEvent.java b/src/newt/classes/com/sun/javafx/newt/WindowEvent.java new file mode 100644 index 000000000..c5aa65e3d --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/WindowEvent.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public class WindowEvent extends Event { + public static final int EVENT_WINDOW_RESIZED = 100; + public static final int EVENT_WINDOW_MOVED = 101; + public static final int EVENT_WINDOW_DESTROY_NOTIFY = 102; + public static final int EVENT_WINDOW_GAINED_FOCUS = 103; + public static final int EVENT_WINDOW_LOST_FOCUS = 104; + // public static final int EVENT_WINDOW_REPAINT = 105; // TODO + + public WindowEvent(int eventType, Window source, long when) { + this(false, eventType, source, when); + } + + WindowEvent(boolean isSystemEvent, int eventType, Window source, long when) { + super(isSystemEvent, eventType, source, when); + } + + public static String getEventTypeString(int type) { + switch(type) { + case EVENT_WINDOW_RESIZED: return "WINDOW_RESIZED"; + case EVENT_WINDOW_MOVED: return "WINDOW_MOVED"; + case EVENT_WINDOW_DESTROY_NOTIFY: return "EVENT_WINDOW_DESTROY_NOTIFY"; + case EVENT_WINDOW_GAINED_FOCUS: return "EVENT_WINDOW_GAINED_FOCUS"; + case EVENT_WINDOW_LOST_FOCUS: return "EVENT_WINDOW_LOST_FOCUS"; + // case EVENT_WINDOW_REPAINT: return "EVENT_WINDOW_REPAINT"; + default: return "unknown (" + type + ")"; + } + } + public String toString() { + return "WindowEvent["+getEventTypeString(getEventType()) + + ", " + super.toString() + "]"; + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/WindowListener.java b/src/newt/classes/com/sun/javafx/newt/WindowListener.java new file mode 100644 index 000000000..81624fa75 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/WindowListener.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt; + +public interface WindowListener extends EventListener { + public void windowResized(WindowEvent e); + public void windowMoved(WindowEvent e); + public void windowDestroyNotify(WindowEvent e); + public void windowGainedFocus(WindowEvent e); + public void windowLostFocus(WindowEvent e); +} diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java new file mode 100644 index 000000000..6b8fc43c7 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTCanvas.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.awt; + +import com.sun.javafx.newt.Window; + +import java.awt.Canvas; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.GraphicsConfiguration; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; +import com.sun.javafx.newt.impl.Debug; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +public class AWTCanvas extends Canvas { + private GraphicsDevice device; + private GraphicsConfiguration chosen; + private AWTGraphicsConfiguration awtConfig; + + private Capabilities capabilities; + + private boolean displayConfigChanged=false; + + public AWTCanvas(Capabilities capabilities) { + super(); + + if(null==capabilities) { + throw new NativeWindowException("Capabilities null"); + } + this.capabilities=capabilities; + } + + public AWTGraphicsConfiguration getAWTGraphicsConfiguration() { + return awtConfig; + } + + public boolean hasDeviceChanged() { + boolean res = displayConfigChanged; + displayConfigChanged=false; + return res; + } + + public void addNotify() { + super.addNotify(); + + disableBackgroundErase(); + + GraphicsConfiguration gc = super.getGraphicsConfiguration(); + if(null!=gc) { + device = gc.getDevice(); + } + + /* + * Save the chosen capabilities for use in getGraphicsConfiguration(). + */ + awtConfig = chooseGraphicsConfiguration(capabilities, device); + if(Window.DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Created Config: "+awtConfig); + e.printStackTrace(); + } + if(null!=awtConfig) { + // update .. + chosen = awtConfig.getGraphicsConfiguration(); + } + if(null==awtConfig) { + throw new NativeWindowException("Error: AWTGraphicsConfiguration is null"); + } + } + + /** + * Overridden to choose a GraphicsConfiguration on a parent container's + * GraphicsDevice because both devices + */ + public GraphicsConfiguration getGraphicsConfiguration() { + /* + * Workaround for problems with Xinerama and java.awt.Component.checkGD + * when adding to a container on a different graphics device than the + * one that this Canvas is associated with. + * + * GC will be null unless: + * - A native peer has assigned it. This means we have a native + * peer, and are already comitted to a graphics configuration. + * - This canvas has been added to a component hierarchy and has + * an ancestor with a non-null GC, but the native peer has not + * yet been created. This means we can still choose the GC on + * all platforms since the peer hasn't been created. + */ + final GraphicsConfiguration gc = super.getGraphicsConfiguration(); + /* + * chosen is only non-null on platforms where the GLDrawableFactory + * returns a non-null GraphicsConfiguration (in the GLCanvas + * constructor). + * + * if gc is from this Canvas' native peer then it should equal chosen, + * otherwise it is from an ancestor component that this Canvas is being + * added to, and we go into this block. + */ + if (gc != null && chosen != null && !chosen.equals(gc)) { + /* + * Check for compatibility with gc. If they differ by only the + * device then return a new GCconfig with the super-class' GDevice + * (and presumably the same visual ID in Xinerama). + * + */ + if (!chosen.getDevice().getIDstring().equals(gc.getDevice().getIDstring())) { + /* + * Here we select a GraphicsConfiguration on the alternate + * device that is presumably identical to the chosen + * configuration, but on the other device. + * + * Should really check to ensure that we select a configuration + * with the same X visual ID for Xinerama screens, otherwise the + * GLDrawable may have the wrong visual ID (I don't think this + * ever gets updated). May need to add a method to + * X11GLDrawableFactory to do this in a platform specific + * manner. + * + * However, on platforms where we can actually get into this + * block, both devices should have the same visual list, and the + * same configuration should be selected here. + */ + AWTGraphicsConfiguration config = chooseGraphicsConfiguration((Capabilities)awtConfig.getRequestedCapabilities(), gc.getDevice()); + final GraphicsConfiguration compatible = (null!=config)?config.getGraphicsConfiguration():null; + if(Window.DEBUG_IMPLEMENTATION) { + Exception e = new Exception("Call Stack: "+Thread.currentThread().getName()); + e.printStackTrace(); + System.err.println("!!! Created Config (n): HAVE GC "+chosen); + System.err.println("!!! Created Config (n): THIS GC "+gc); + System.err.println("!!! Created Config (n): Choosen GC "+compatible); + System.err.println("!!! Created Config (n): HAVE CF "+awtConfig); + System.err.println("!!! Created Config (n): Choosen CF "+config); + System.err.println("!!! Created Config (n): EQUALS CAPS "+config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())); + } + + if (compatible != null) { + /* + * Save the new GC for equals test above, and to return to + * any outside callers of this method. + */ + chosen = compatible; + if( !config.getChosenCapabilities().equals(awtConfig.getChosenCapabilities())) { + displayConfigChanged=true; + } + awtConfig = config; + } + } + + /* + * If a compatible GC was not found in the block above, this will + * return the GC that was selected in the constructor (and might + * cause an exception in Component.checkGD when adding to a + * container, but in this case that would be the desired behavior). + * + */ + return chosen; + } else if (gc == null) { + /* + * The GC is null, which means we have no native peer, and are not + * part of a (realized) component hierarchy. So we return the + * desired visual that was selected in the constructor (possibly + * null). + */ + return chosen; + } + + /* + * Otherwise we have not explicitly selected a GC in the constructor, so + * just return what Canvas would have. + */ + return gc; + } + + private static AWTGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + GraphicsDevice device) { + AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device); + AWTGraphicsConfiguration config = (AWTGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class).chooseGraphicsConfiguration(capabilities, + null, + aScreen); + if (config == null) { + throw new NativeWindowException("Error: Couldn't fetch AWTGraphicsConfiguration"); + } + + return config; + } + + // Disables the AWT's erasing of this Canvas's background on Windows + // in Java SE 6. This internal API is not available in previous + // releases, but the system property + // -Dsun.awt.noerasebackground=true can be specified to get similar + // results globally in previous releases. + private static boolean disableBackgroundEraseInitialized; + private static Method disableBackgroundEraseMethod; + private void disableBackgroundErase() { + if (!disableBackgroundEraseInitialized) { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class clazz = getToolkit().getClass(); + while (clazz != null && disableBackgroundEraseMethod == null) { + try { + disableBackgroundEraseMethod = + clazz.getDeclaredMethod("disableBackgroundErase", + new Class[] { Canvas.class }); + disableBackgroundEraseMethod.setAccessible(true); + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + } catch (Exception e) { + } + return null; + } + }); + } catch (Exception e) { + } + disableBackgroundEraseInitialized = true; + } + if (disableBackgroundEraseMethod != null) { + try { + disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this }); + } catch (Exception e) { + // FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10) + // throw new GLException(e); + } + } + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java new file mode 100644 index 000000000..099125630 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTDisplay.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.awt; + +import java.awt.*; +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +public class AWTDisplay extends Display { + public AWTDisplay() { + } + + protected void createNative() { + aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default + } + + protected void setAWTGraphicsDevice(AWTGraphicsDevice d) { + aDevice = d; + } + + protected void closeNative() { } +} diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java new file mode 100644 index 000000000..9bda5893b --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTScreen.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.awt; + +import com.sun.javafx.newt.*; +import java.awt.DisplayMode; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +public class AWTScreen extends Screen { + public AWTScreen() { + } + + protected void createNative(int index) { + aScreen = new AWTGraphicsScreen((AWTGraphicsDevice)display.getGraphicsDevice()); + + DisplayMode mode = ((AWTGraphicsDevice)getDisplay().getGraphicsDevice()).getGraphicsDevice().getDisplayMode(); + int w = mode.getWidth(); + int h = mode.getHeight(); + setScreenSize(w, h); + } + + protected void setAWTGraphicsScreen(AWTGraphicsScreen s) { + aScreen = s; + } + + // done by AWTWindow .. + protected void setScreenSize(int w, int h) { + super.setScreenSize(w, h); + } + + protected void closeNative() { } + +} diff --git a/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java new file mode 100644 index 000000000..3742a0e57 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/awt/AWTWindow.java @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.awt; + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.DisplayMode; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.awt.event.*; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.*; +import com.sun.javafx.newt.Window; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +/** An implementation of the Newt Window class built using the + AWT. This is provided for convenience of porting to platforms + supporting Java SE. */ + +public class AWTWindow extends Window { + + public AWTWindow() { + super(); + title = "AWT NewtWindow"; + } + + private Frame frame; + private AWTCanvas canvas; + private LinkedList/*<AWTEventWrapper>*/ events = new LinkedList(); + // non fullscreen dimensions .. + private int nfs_width, nfs_height, nfs_x, nfs_y; + + public void setTitle(final String title) { + super.setTitle(title); + runOnEDT(true, new Runnable() { + public void run() { + if (frame != null) { + frame.setTitle(title); + } + } + }); + } + + protected void createNative(final Capabilities caps) { + + runOnEDT(true, new Runnable() { + public void run() { + frame = new Frame(getTitle()); + frame.setUndecorated(isUndecorated()); + frame.setLayout(new BorderLayout()); + canvas = new AWTCanvas(caps); + Listener listener = new Listener(); + canvas.addMouseListener(listener); + canvas.addMouseMotionListener(listener); + canvas.addKeyListener(listener); + canvas.addComponentListener(listener); + frame.add(canvas, BorderLayout.CENTER); + frame.setSize(width, height); + frame.setLocation(x, y); + frame.addComponentListener(new MoveListener()); + frame.addWindowListener(new WindowEventListener()); + } + }); + } + + protected void closeNative() { + runOnEDT(true, new Runnable() { + public void run() { + frame.dispose(); + frame = null; + } + }); + } + + public boolean hasDeviceChanged() { + boolean res = canvas.hasDeviceChanged(); + if(res) { + config = canvas.getAWTGraphicsConfiguration(); + if (config == null) { + throw new NativeWindowException("Error Device change null GraphicsConfiguration: "+this); + } + updateDeviceData(); + } + return res; + } + + public void setVisible(final boolean visible) { + runOnEDT(true, new Runnable() { + public void run() { + frame.setVisible(visible); + } + }); + + config = canvas.getAWTGraphicsConfiguration(); + + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + updateDeviceData(); + } + + private void updateDeviceData() { + // propagate new info .. + ((AWTScreen)getScreen()).setAWTGraphicsScreen((AWTGraphicsScreen)config.getScreen()); + ((AWTDisplay)getScreen().getDisplay()).setAWTGraphicsDevice((AWTGraphicsDevice)config.getScreen().getDevice()); + + DisplayMode mode = ((AWTGraphicsDevice)config.getScreen().getDevice()).getGraphicsDevice().getDisplayMode(); + int w = mode.getWidth(); + int h = mode.getHeight(); + ((AWTScreen)screen).setScreenSize(w, h); + } + + public void setSize(final int width, final int height) { + this.width = width; + this.height = height; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ + runOnEDT(false, new Runnable() { + public void run() { + frame.setSize(width, height); + } + }); + } + + public void setPosition(final int x, final int y) { + this.x = x; + this.y = y; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + runOnEDT(true, new Runnable() { + public void run() { + frame.setLocation(x, y); + } + }); + } + + public boolean setFullscreen(final boolean fullscreen) { + if(this.fullscreen!=fullscreen) { + final int x,y,w,h; + this.fullscreen=fullscreen; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("AWTWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ + runOnEDT(false, new Runnable() { + public void run() { + if(!frame.isDisplayable()) { + frame.setUndecorated(fullscreen); + } else { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("AWTWindow can't undecorate already created frame"); + } + } + frame.setLocation(x, y); + frame.setSize(w, h); + } + }); + } + return true; + } + + public Object getWrappedWindow() { + return canvas; + } + + public void dispatchMessages(int eventMask) { + AWTEventWrapper w; + do { + synchronized(this) { + if (!events.isEmpty()) { + w = (AWTEventWrapper) events.removeFirst(); + } else { + w = null; + } + } + if (w != null) { + switch (w.getType()) { + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED: + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED: + case com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY: + if ((eventMask & com.sun.javafx.newt.EventListener.WINDOW) != 0) { + sendWindowEvent(w.getType()); + } + break; + + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_CLICKED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED: + case com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_WHEEL_MOVED: + if ((eventMask & com.sun.javafx.newt.EventListener.MOUSE) != 0) { + MouseEvent e = (MouseEvent) w.getEvent(); + int rotation = 0; + if (e instanceof MouseWheelEvent) { + rotation = ((MouseWheelEvent)e).getWheelRotation(); + } + sendMouseEvent(w.getType(), convertModifiers(e), + e.getX(), e.getY(), convertButton(e), + rotation); + } + break; + + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED: + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED: + case com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED: + if ((eventMask & com.sun.javafx.newt.EventListener.KEY) != 0) { + KeyEvent e = (KeyEvent) w.getEvent(); + sendKeyEvent(w.getType(), convertModifiers(e), + e.getKeyCode(), e.getKeyChar()); + } + break; + + default: + throw new NativeWindowException("Unknown event type " + w.getType()); + } + if(Window.DEBUG_MOUSE_EVENT) { + System.out.println("dispatchMessages: in event:"+w.getEvent()); + } + } + } while (w != null); + } + + private static int convertModifiers(InputEvent e) { + int newtMods = 0; + int mods = e.getModifiers(); + if ((mods & InputEvent.SHIFT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.SHIFT_MASK; + if ((mods & InputEvent.CTRL_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.CTRL_MASK; + if ((mods & InputEvent.META_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.META_MASK; + if ((mods & InputEvent.ALT_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_MASK; + if ((mods & InputEvent.ALT_GRAPH_MASK) != 0) newtMods |= com.sun.javafx.newt.InputEvent.ALT_GRAPH_MASK; + return newtMods; + } + + private static int convertButton(MouseEvent e) { + switch (e.getButton()) { + case MouseEvent.BUTTON1: return com.sun.javafx.newt.MouseEvent.BUTTON1; + case MouseEvent.BUTTON2: return com.sun.javafx.newt.MouseEvent.BUTTON2; + case MouseEvent.BUTTON3: return com.sun.javafx.newt.MouseEvent.BUTTON3; + } + return 0; + } + + private static void runOnEDT(boolean wait, Runnable r) { + if (EventQueue.isDispatchThread()) { + r.run(); + } else { + try { + if(wait) { + EventQueue.invokeAndWait(r); + } else { + EventQueue.invokeLater(r); + } + } catch (Exception e) { + throw new NativeWindowException(e); + } + } + } + + private void enqueueEvent(int type, InputEvent e) { + AWTEventWrapper wrapper = new AWTEventWrapper(type, e); + synchronized(this) { + events.add(wrapper); + } + } + + private static final int WINDOW_EVENT = 1; + private static final int KEY_EVENT = 2; + private static final int MOUSE_EVENT = 3; + + static class AWTEventWrapper { + int type; + InputEvent e; + + AWTEventWrapper(int type, InputEvent e) { + this.type = type; + this.e = e; + } + + public int getType() { + return type; + } + + public InputEvent getEvent() { + return e; + } + } + + class MoveListener implements ComponentListener { + public void componentResized(ComponentEvent e) { + } + + public void componentMoved(ComponentEvent e) { + x = frame.getX(); + y = frame.getY(); + enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_MOVED, null); + } + + public void componentShown(ComponentEvent e) { + } + + public void componentHidden(ComponentEvent e) { + } + + } + + class Listener implements ComponentListener, MouseListener, MouseMotionListener, KeyListener { + public void componentResized(ComponentEvent e) { + width = canvas.getWidth(); + height = canvas.getHeight(); + enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_RESIZED, null); + } + + public void componentMoved(ComponentEvent e) { + } + + public void componentShown(ComponentEvent e) { + } + + public void componentHidden(ComponentEvent e) { + } + + public void mouseClicked(MouseEvent e) { + // We ignore these as we synthesize them ourselves out of + // mouse pressed and released events + } + + public void mouseEntered(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_ENTERED, e); + } + + public void mouseExited(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_EXITED, e); + } + + public void mousePressed(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_PRESSED, e); + } + + public void mouseReleased(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_RELEASED, e); + } + + public void mouseMoved(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_MOVED, e); + } + + public void mouseDragged(MouseEvent e) { + enqueueEvent(com.sun.javafx.newt.MouseEvent.EVENT_MOUSE_DRAGGED, e); + } + + public void keyPressed(KeyEvent e) { + enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_PRESSED, e); + } + + public void keyReleased(KeyEvent e) { + enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_RELEASED, e); + } + + public void keyTyped(KeyEvent e) { + enqueueEvent(com.sun.javafx.newt.KeyEvent.EVENT_KEY_TYPED, e); + } + } + + class WindowEventListener implements WindowListener { + public void windowActivated(WindowEvent e) { + } + public void windowClosed(WindowEvent e) { + } + public void windowClosing(WindowEvent e) { + enqueueEvent(com.sun.javafx.newt.WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY, null); + } + public void windowDeactivated(WindowEvent e) { + } + public void windowDeiconified(WindowEvent e) { + } + public void windowIconified(WindowEvent e) { + } + public void windowOpened(WindowEvent e) { + } + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/impl/Debug.java b/src/newt/classes/com/sun/javafx/newt/impl/Debug.java new file mode 100644 index 000000000..a901eafb1 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/impl/Debug.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.javafx.newt.impl; + +import java.security.*; + +/** Helper routines for logging and debugging. */ + +public class Debug { + // Some common properties + private static boolean verbose; + private static boolean debugAll; + + static { + verbose = isPropertyDefined("newt.verbose"); + debugAll = isPropertyDefined("newt.debug"); + if (verbose) { + Package p = Package.getPackage("com.sun.javafx.newt"); + System.err.println("NEWT specification version " + p.getSpecificationVersion()); + System.err.println("NEWT implementation version " + p.getImplementationVersion()); + System.err.println("NEWT implementation vendor " + p.getImplementationVendor()); + } + } + + public static boolean getBooleanProperty(final String property) { + Boolean b = (Boolean) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + boolean val = Boolean.getBoolean(property); + return (val ? Boolean.TRUE : Boolean.FALSE); + } + }); + return b.booleanValue(); + } + + public static boolean isPropertyDefined(final String property) { + Boolean b = (Boolean) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String val = System.getProperty(property); + return (val != null ? Boolean.TRUE : Boolean.FALSE); + } + }); + return b.booleanValue(); + } + + public static boolean verbose() { + return verbose; + } + + public static boolean debugAll() { + return debugAll; + } + + public static boolean debug(String subcomponent) { + return debugAll() || isPropertyDefined("newt.debug." + subcomponent); + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/impl/NativeLibLoader.java b/src/newt/classes/com/sun/javafx/newt/impl/NativeLibLoader.java new file mode 100644 index 000000000..06d76b294 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/impl/NativeLibLoader.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.javafx.newt.impl; + +// FIXME: refactor Java SE dependencies +//import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashSet; +import com.sun.nativewindow.impl.NativeLibLoaderBase; + +public class NativeLibLoader extends NativeLibLoaderBase { + + public static void loadNEWT() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String[] preload = { "nativewindow" }; + loadLibrary("newt", preload, true); + return null; + } + }); + } + + //---------------------------------------------------------------------- + // Support for the new JNLPAppletLauncher + // + + private static class NEWTAction implements NativeLibLoaderBase.LoaderAction { + public void loadLibrary(String libname, String[] preload, + boolean preloadIgnoreError) { + if (null!=preload) { + for (int i=0; i<preload.length; i++) { + if(!isLoaded(preload[i])) { + try { + if(DEBUG) { + System.err.println("NEWT NativeLibLoader preload "+preload[i]); + } + loadLibraryInternal(preload[i]); + addLoaded(preload[i]); + } + catch (UnsatisfiedLinkError e) { + if (!preloadIgnoreError && e.getMessage().indexOf("already loaded") < 0) { + throw e; + } + } + } + } + } + + if(DEBUG) { + System.err.println("NEWT NativeLibLoader load "+libname); + } + loadLibraryInternal(libname); + addLoaded(libname); + } + } + + private static boolean usingJNLPAppletLauncher; + private static Method jnlpLoadLibraryMethod; + + static { + NativeLibLoaderBase.setLoadingAction(new NEWTAction()); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String sunAppletLauncher = System.getProperty("sun.jnlp.applet.launcher"); + usingJNLPAppletLauncher = Boolean.valueOf(sunAppletLauncher).booleanValue(); + return null; + } + }); + } + + // I hate the amount of delegation currently in this class + private static void loadLibraryInternal(String libraryName) { + // Note: special-casing JAWT which is built in to the JDK + if (usingJNLPAppletLauncher && !libraryName.equals("jawt")) { + try { + if (jnlpLoadLibraryMethod == null) { + Class jnlpAppletLauncherClass = Class.forName("org.jdesktop.applet.util.JNLPAppletLauncher"); + jnlpLoadLibraryMethod = jnlpAppletLauncherClass.getDeclaredMethod("loadLibrary", new Class[] { String.class }); + } + jnlpLoadLibraryMethod.invoke(null, new Object[] { libraryName }); + } catch (Exception e) { + Throwable t = e; + if (t instanceof InvocationTargetException) { + t = ((InvocationTargetException) t).getTargetException(); + } + if (t instanceof Error) + throw (Error) t; + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + // Throw UnsatisfiedLinkError for best compatibility with System.loadLibrary() + throw (UnsatisfiedLinkError) new UnsatisfiedLinkError().initCause(e); + } + } else { + // FIXME: remove + // System.out.println("sun.boot.library.path=" + System.getProperty("sun.boot.library.path")); + System.loadLibrary(libraryName); + if(DEBUG) { + System.err.println("NEWT NativeLibLoader loaded "+libraryName); + } + } + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java new file mode 100755 index 000000000..29b7151f4 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacDisplay.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.macosx; + +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.*; + +public class MacDisplay extends Display { + public MacDisplay() { + } + + protected void createNative() { + aDevice = new MacOSXGraphicsDevice(); + } + + protected void closeNative() { } +} diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java new file mode 100755 index 000000000..06ef8aacd --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacScreen.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.macosx; + +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; + +public class MacScreen extends Screen { + public MacScreen() { + MacWindow.initSingleton(); + } + + protected void createNative(int index) { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + setScreenSize(MacWindow.getScreenWidth(getIndex()), MacWindow.getScreenHeight(getIndex())); + } + + protected void closeNative() { } +} diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java new file mode 100755 index 000000000..2c1ca7c89 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.macosx; + +import javax.media.nativewindow.*; + +import com.sun.javafx.newt.util.MainThread; +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; + +public class MacWindow extends Window { + + private static native boolean initIDs(); + + // Window styles + private static final int NSBorderlessWindowMask = 0; + private static final int NSTitledWindowMask = 1 << 0; + 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; + + // sync the MacOSX resources .. NSView, ie toggle fullscreen, window create + private Object nsViewLock = new Object(); + + private volatile long surfaceHandle; + // non fullscreen dimensions .. + private int nfs_width, nfs_height, nfs_x, nfs_y; + + static { + initSingleton(); + } + + private static volatile boolean isInit = false; + + public static synchronized void initSingleton() { + if(isInit) return; + isInit=true; + + NativeLibLoader.loadNEWT(); + + if(!initIDs()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.initIDs OK "+Thread.currentThread().getName()); + } + + public MacWindow() { + } + + protected void createNative(Capabilities caps) { + config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + } + + class CloseAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); + if (windowHandle != 0) { + close0(windowHandle); + windowHandle = 0; + } + } + } + } + private CloseAction closeAction = new CloseAction(); + + protected void closeNative() { + MainThread.invoke(true, closeAction); + } + + public long getWindowHandle() { + synchronized(nsViewLock) { + return windowHandle; + } + } + + public long getSurfaceHandle() { + synchronized(nsViewLock) { + return surfaceHandle; + } + } + + class VisibleAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); + if (visible) { + createWindow(false); + } else { + if (windowHandle != 0) { + orderOut(windowHandle); + } + } + } + } + } + private VisibleAction visibleAction = new VisibleAction(); + + public void setVisible(boolean visible) { + this.visible = visible; + MainThread.invoke(true, visibleAction); + } + + class TitleAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if (windowHandle != 0) { + setTitle0(windowHandle, title); + } + } + } + } + private TitleAction titleAction = new TitleAction(); + + public void setTitle(String title) { + super.setTitle(title); + MainThread.invoke(true, titleAction); + } + + class FocusAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if (windowHandle != 0) { + makeKey(windowHandle); + } + } + } + } + private FocusAction focusAction = new FocusAction(); + + public void requestFocus() { + super.requestFocus(); + MainThread.invoke(true, focusAction); + } + + class SizeAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if (windowHandle != 0) { + setContentSize(windowHandle, width, height); + } + } + } + } + private SizeAction sizeAction = new SizeAction(); + + public void setSize(int width, int height) { + this.width=width; + this.height=height; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + MainThread.invoke(true, sizeAction); + } + + class PositionAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if (windowHandle != 0) { + setFrameTopLeftPoint(windowHandle, x, y); + } + } + } + } + private PositionAction positionAction = new PositionAction(); + + public void setPosition(int x, int y) { + this.x=x; + this.y=y; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + MainThread.invoke(true, positionAction); + } + + class DispatchAction implements Runnable { + public void run() { + dispatchMessages0(windowHandle, eventMask); + } + } + private DispatchAction dispatchAction = new DispatchAction(); + private int eventMask; + + public void dispatchMessages(int eventMask) { + this.eventMask=eventMask; + MainThread.invoke(false, dispatchAction); + } + + class FullscreenAction implements Runnable { + public void run() { + synchronized(nsViewLock) { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); + } + createWindow(true); + } + } + } + private FullscreenAction fullscreenAction = new FullscreenAction(); + + public boolean setFullscreen(boolean fullscreen) { + if(this.fullscreen!=fullscreen) { + this.fullscreen=fullscreen; + if(fullscreen) { + x = 0; + y = 0; + width = screen.getWidth(); + height = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + width = nfs_width; + height = nfs_height; + } + MainThread.invoke(true, fullscreenAction); + } + return fullscreen; + } + + private void sizeChanged(int newWidth, int newHeight) { + if (DEBUG_IMPLEMENTATION) { + System.out.println(Thread.currentThread().getName()+" Size changed to " + newWidth + ", " + newHeight); + } + width = newWidth; + height = newHeight; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + if (DEBUG_IMPLEMENTATION) { + System.out.println(" Posted WINDOW_RESIZED event"); + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + } + + private void positionChanged(int newX, int newY) { + if (DEBUG_IMPLEMENTATION) { + System.out.println(Thread.currentThread().getName()+" Position changed to " + newX + ", " + newY); + } + x = newX; + y = newY; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + if (DEBUG_IMPLEMENTATION) { + System.out.println(" Posted WINDOW_MOVED event"); + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + } + + private void focusChanged(boolean focusGained) { + if (focusGained) { + sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + } else { + sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + } + } + + 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; + } + + protected void sendKeyEvent(int eventType, int modifiers, int keyCode, char keyChar) { + int key = convertKeyChar(keyChar); + if(DEBUG_IMPLEMENTATION) System.out.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); + } + + private void createWindow(boolean recreate) { + if(0!=windowHandle && !recreate) { + return; + } + if(0!=windowHandle) { + // save the view .. close the window + surfaceHandle = changeContentView(windowHandle, 0); + if(recreate && 0==surfaceHandle) { + throw new NativeWindowException("Internal Error - recreate, window but no view"); + } + close0(windowHandle); + windowHandle=0; + } else { + surfaceHandle = 0; + } + windowHandle = createWindow0(getX(), getY(), getWidth(), getHeight(), fullscreen, + (isUndecorated() ? + NSBorderlessWindowMask : + NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), + NSBackingStoreBuffered, + getScreen().getIndex(), surfaceHandle); + if (windowHandle == 0) { + throw new NativeWindowException("Could create native window "+Thread.currentThread().getName()+" "+this); + } + surfaceHandle = contentView(windowHandle); + setTitle0(windowHandle, getTitle()); + makeKeyAndOrderFront(windowHandle); + sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + } + + private native long createWindow0(int x, int y, int w, int h, + boolean fullscreen, int windowStyle, + int backingStoreType, + int screen_idx, long view); + private native void makeKeyAndOrderFront(long window); + private native void makeKey(long window); + private native void orderOut(long window); + private native void close0(long window); + private native void setTitle0(long window, String title); + protected native void dispatchMessages0(long window, int eventMask); + private native long contentView(long window); + private native long changeContentView(long window, long view); + private native void setContentSize(long window, int w, int h); + private native void setFrameTopLeftPoint(long window, int x, int y); + protected static native int getScreenWidth(int scrn_idx); + protected static native int getScreenHeight(int scrn_idx); +} diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java new file mode 100644 index 000000000..5d50792db --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/opengl/GLWindow.java @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.opengl; + +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.sun.opengl.impl.GLDrawableHelper; + +/** + * An implementation of {@link Window} which is customized for OpenGL + * use, and which implements the {@link + * javax.media.opengl.GLAutoDrawable} interface. For convenience, this + * window class guarantees that its OpenGL context is current inside + * the various EventListeners' callbacks (MouseListener, KeyListener, + * etc.). + */ +public class GLWindow extends Window implements GLAutoDrawable { + /** + * Event handling mode: EVENT_HANDLER_GL_NONE. + * No GL context is current, while calling the EventListener. + * This might be inconvenient, but don't impact the performance. + * + * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int) + */ + public static final int EVENT_HANDLER_GL_NONE = 0; + + /** + * Event handling mode: EVENT_HANDLER_GL_CURRENT. + * The GL context is made current, while calling the EventListener. + * This might be convenient, but impacts the performance + * due to context switches. + * + * This is the default setting! + * + * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int) + */ + public static final int EVENT_HANDLER_GL_CURRENT = (1 << 0); + + private Window window; + + /** Constructor. Do not call this directly -- use {@link + create()} instead. */ + protected GLWindow(Window window, boolean ownerOfDisplayAndScreen) { + this.ownerOfDisplayAndScreen = ownerOfDisplayAndScreen; + this.window = window; + this.window.setAutoDrawableClient(true); + window.addWindowListener(new WindowListener() { + public void windowResized(WindowEvent e) { + sendReshape = true; + } + + public void windowMoved(WindowEvent e) { + } + + public void windowGainedFocus(WindowEvent e) { + } + + public void windowLostFocus(WindowEvent e) { + } + + public void windowDestroyNotify(WindowEvent e) { + sendDestroy = true; + } + }); + } + + /** Creates a new GLWindow on the local display, screen 0, with a + dummy visual ID, and with the default GLCapabilities. */ + public static GLWindow create() { + return create(null, null, false); + } + + public static GLWindow create(boolean undecorated) { + return create(null, null, undecorated); + } + + /** Creates a new GLWindow referring to the given window. */ + public static GLWindow create(Window window) { + return create(window, null, false); + } + public static GLWindow create(GLCapabilities caps) { + return create(null, caps, false); + } + + /** Creates a new GLWindow on the local display, screen 0, with a + dummy visual ID, and with the given GLCapabilities. */ + public static GLWindow create(GLCapabilities caps, boolean undecorated) { + return create(null, caps, undecorated); + } + + /** Creates a new GLWindow referring to the given window, and with the given GLCapabilities. */ + public static GLWindow create(Window window, GLCapabilities caps) { + return create(window, caps, false); + } + + public static GLWindow create(Window window, + GLCapabilities caps, + boolean undecorated) { + if (caps == null) { + caps = new GLCapabilities(null); // default .. + } + + boolean ownerOfDisplayAndScreen=false; + if (window == null) { + ownerOfDisplayAndScreen = true; + Display display = NewtFactory.createDisplay(null); // local display + Screen screen = NewtFactory.createScreen(display, 0); // screen 0 + window = NewtFactory.createWindow(screen, caps, undecorated); + } + + return new GLWindow(window, ownerOfDisplayAndScreen); + } + + protected void createNative(Capabilities caps) { + shouldNotCallThis(); + } + + protected void closeNative() { + shouldNotCallThis(); + } + + protected void dispose(boolean regenerate) { + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", 1: "+this); + e1.printStackTrace(); + } + + sendDisposeEvent(); + + if (context != null) { + context.destroy(); + } + if (drawable != null) { + drawable.setRealized(false); + } + + if(null!=window) { + window.disposeSurfaceHandle(); + } + + if(regenerate) { + if(null==window) { + throw new GLException("GLWindow.dispose(true): null window"); + } + + // recreate GLDrawable, to reflect the new graphics configurations + NativeWindow nw; + if (window.getWrappedWindow() != null) { + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; + } + drawable = factory.createGLDrawable(nw); + drawable.setRealized(true); + if(getSurfaceHandle()==0) { + throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this); + } + context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. + } + + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", fin: "+this); + } + } + + public synchronized void destroy() { + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + Exception e1 = new Exception("GLWindow.destroy "+Thread.currentThread().getName()+", 1: "+this); + e1.printStackTrace(); + } + + dispose(false); + + Screen _screen = null; + Display _device = null; + if(null!=window) { + if(ownerOfDisplayAndScreen) { + _screen = getScreen(); + if(null != _screen) { + _device = _screen.getDisplay(); + } + } + window.destroy(); + } + + if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { + System.out.println("GLWindow.destroy "+Thread.currentThread().getName()+", fin: "+this); + } + + drawable = null; + context = null; + + if(null != _screen) { + _screen.destroy(); + } + if(null != _device) { + _device.destroy(); + } + window = null; + } + + public boolean getPerfLogEnabled() { return perfLog; } + + public void enablePerfLog(boolean v) { + perfLog = v; + } + + /** + * Sets the event handling mode. + * + * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_NONE + * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_CURRENT + */ + public void setEventHandlerMode(int mode) { + eventHandlerMode = mode; + } + + public int getEventHandlerMode() { + return eventHandlerMode; + } + + public void pumpMessages(int eventMask) { + if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) { + window.pumpMessages(eventMask); + } else { + pumpMessagesWithEventMaskAction.eventMask = eventMask; + pumpMessagesImpl(pumpMessagesWithEventMaskAction); + } + } + + public void pumpMessages() { + if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) { + window.pumpMessages(); + } else { + pumpMessagesImpl(pumpMessagesAction); + } + } + + class PumpMessagesWithEventMaskAction implements Runnable { + private int eventMask; + + public void run() { + window.pumpMessages(eventMask); + } + } + private PumpMessagesWithEventMaskAction pumpMessagesWithEventMaskAction = new PumpMessagesWithEventMaskAction(); + + class PumpMessagesAction implements Runnable { + public void run() { + window.pumpMessages(); + } + } + private PumpMessagesAction pumpMessagesAction = new PumpMessagesAction(); + + private void pumpMessagesImpl(Runnable pumpMessagesAction) { + // pumpMessagesAction.run(); + + boolean autoSwapBuffer = helper.getAutoSwapBufferMode(); + helper.setAutoSwapBufferMode(false); + try { + helper.invokeGL(drawable, context, pumpMessagesAction, initAction); + } finally { + helper.setAutoSwapBufferMode(autoSwapBuffer); + } + + } + + protected void dispatchMessages(int eventMask) { + shouldNotCallThis(); + } + + public void setVisible(boolean visible) { + window.setVisible(visible); + if (visible && context == null) { + NativeWindow nw; + if (window.getWrappedWindow() != null) { + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; + } + GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); + drawable = factory.createGLDrawable(nw); + drawable.setRealized(true); + if(getSurfaceHandle()==0) { + throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this); + } + context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. + } + } + + public Screen getScreen() { + return window.getScreen(); + } + + public void setTitle(String title) { + window.setTitle(title); + } + + public String getTitle() { + return window.getTitle(); + } + + public void setUndecorated(boolean value) { + window.setUndecorated(value); + } + + public boolean isUndecorated() { + return window.isUndecorated(); + } + + public void setSize(int width, int height) { + window.setSize(width, height); + } + + public void setPosition(int x, int y) { + window.setPosition(x, y); + } + + public boolean setFullscreen(boolean fullscreen) { + return window.setFullscreen(fullscreen); + } + + public boolean isVisible() { + return window.isVisible(); + } + + public int getX() { + return window.getX(); + } + + public int getY() { + return window.getY(); + } + + public int getWidth() { + return window.getWidth(); + } + + public int getHeight() { + return window.getHeight(); + } + + public boolean isFullscreen() { + return window.isFullscreen(); + } + + public void addMouseListener(MouseListener l) { + window.addMouseListener(l); + } + + public void removeMouseListener(MouseListener l) { + window.removeMouseListener(l); + } + + public MouseListener[] getMouseListeners() { + return window.getMouseListeners(); + } + + public void addKeyListener(KeyListener l) { + window.addKeyListener(l); + } + + public void removeKeyListener(KeyListener l) { + window.removeKeyListener(l); + } + + public KeyListener[] getKeyListeners() { + return window.getKeyListeners(); + } + + public void addWindowListener(WindowListener l) { + window.addWindowListener(l); + } + + public void removeWindowListener(WindowListener l) { + window.removeWindowListener(l); + } + + public WindowListener[] getWindowListeners() { + return window.getWindowListeners(); + } + + public String toString() { + return "NEWT-GLWindow[ "+drawable+", \n\t"+window+", \n\t"+helper+", \n\t"+factory+"]"; + } + + //---------------------------------------------------------------------- + // OpenGL-related methods and state + // + + private int eventHandlerMode = EVENT_HANDLER_GL_CURRENT; + private GLDrawableFactory factory; + private GLDrawable drawable; + private GLContext context; + private GLDrawableHelper helper = new GLDrawableHelper(); + // To make reshape events be sent immediately before a display event + private boolean sendReshape=false; + private boolean sendDestroy=false; + private boolean perfLog = false; + + public GLDrawableFactory getFactory() { + return factory; + } + + public void setContext(GLContext newCtx) { + context = newCtx; + } + + public GLContext getContext() { + return context; + } + + public GL getGL() { + if (context == null) { + return null; + } + return context.getGL(); + } + + public void setGL(GL gl) { + if (context != null) { + context.setGL(gl); + } + } + + public void addGLEventListener(GLEventListener listener) { + helper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + helper.removeGLEventListener(listener); + } + + public void display() { + if(getSurfaceHandle()!=0) { + pumpMessages(); + if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { + dispose(true); + } + if (sendDestroy) { + destroy(); + sendDestroy=false; + } else { + helper.invokeGL(drawable, context, displayAction, initAction); + } + } + } + + private void sendDisposeEvent() { + if(disposeAction!=null && drawable!=null && context != null && window!=null && getSurfaceHandle()!=0) { + helper.invokeGL(drawable, context, disposeAction, null); + } + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + helper.setAutoSwapBufferMode(onOrOff); + } + + public boolean getAutoSwapBufferMode() { + return helper.getAutoSwapBufferMode(); + } + + public void swapBuffers() { + if(getSurfaceHandle()!=0) { + if (context != null && context != GLContext.getCurrent()) { + // Assume we should try to make the context current before swapping the buffers + helper.invokeGL(drawable, context, swapBuffersAction, initAction); + } else { + drawable.swapBuffers(); + } + } + } + + class InitAction implements Runnable { + public void run() { + helper.init(GLWindow.this); + startTime = System.currentTimeMillis(); + curTime = startTime; + if(perfLog) { + lastCheck = startTime; + totalFrames = 0; lastFrames = 0; + } + } + } + private InitAction initAction = new InitAction(); + + class DisposeAction implements Runnable { + public void run() { + helper.dispose(GLWindow.this); + } + } + private DisposeAction disposeAction = new DisposeAction(); + + class DisplayAction implements Runnable { + public void run() { + if (sendReshape) { + int width = getWidth(); + int height = getHeight(); + getGL().glViewport(0, 0, width, height); + helper.reshape(GLWindow.this, 0, 0, width, height); + sendReshape = false; + } + + helper.display(GLWindow.this); + + curTime = System.currentTimeMillis(); + totalFrames++; + + if(perfLog) { + long dt0, dt1; + lastFrames++; + dt0 = curTime-lastCheck; + if ( dt0 > 5000 ) { + dt1 = curTime-startTime; + System.out.println(dt0/1000 +"s: "+ lastFrames + "f, " + (lastFrames*1000)/dt0 + " fps, "+dt0/lastFrames+" ms/f; "+ + "total: "+ dt1/1000+"s, "+(totalFrames*1000)/dt1 + " fps, "+dt1/totalFrames+" ms/f"); + lastCheck=curTime; + lastFrames=0; + } + } + } + } + + public long getStartTime() { return startTime; } + public long getCurrentTime() { return curTime; } + public long getDuration() { return curTime-startTime; } + public int getTotalFrames() { return totalFrames; } + + private long startTime = 0; + private long curTime = 0; + private long lastCheck = 0; + private int totalFrames = 0, lastFrames = 0; + private boolean ownerOfDisplayAndScreen; + + private DisplayAction displayAction = new DisplayAction(); + + class SwapBuffersAction implements Runnable { + public void run() { + drawable.swapBuffers(); + } + } + + private SwapBuffersAction swapBuffersAction = new SwapBuffersAction(); + + //---------------------------------------------------------------------- + // GLDrawable methods + // + + public NativeWindow getNativeWindow() { + return null!=drawable ? drawable.getNativeWindow() : null; + } + + public synchronized int lockSurface() throws NativeWindowException { + if(null!=drawable) return drawable.getNativeWindow().lockSurface(); + return NativeWindow.LOCK_SURFACE_NOT_READY; + } + + public synchronized void unlockSurface() { + if(null!=drawable) drawable.getNativeWindow().unlockSurface(); + else throw new NativeWindowException("NEWT-GLWindow not locked"); + } + + public synchronized boolean isSurfaceLocked() { + if(null!=drawable) return drawable.getNativeWindow().isSurfaceLocked(); + return false; + } + + public synchronized Exception getLockedStack() { + if(null!=drawable) return drawable.getNativeWindow().getLockedStack(); + return null; + } + + public long getWindowHandle() { + if(null!=drawable) return drawable.getNativeWindow().getWindowHandle(); + return super.getWindowHandle(); + } + + public long getSurfaceHandle() { + if(null!=drawable) return drawable.getNativeWindow().getSurfaceHandle(); + return super.getSurfaceHandle(); + } + + //---------------------------------------------------------------------- + // GLDrawable methods that are not really needed + // + + public GLContext createContext(GLContext shareWith) { + return drawable.createContext(shareWith); + } + + public void setRealized(boolean realized) { + } + + public GLCapabilities getChosenGLCapabilities() { + if (drawable == null) { + throw new GLException("No drawable yet"); + } + + return drawable.getChosenGLCapabilities(); + } + + public GLProfile getGLProfile() { + if (drawable == null) { + throw new GLException("No drawable yet"); + } + + return drawable.getGLProfile(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void shouldNotCallThis() { + throw new NativeWindowException("Should not call this"); + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java new file mode 100755 index 000000000..a13a95586 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDDisplay.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.opengl.kd; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import com.sun.opengl.impl.egl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; + +public class KDDisplay extends Display { + static { + NativeLibLoader.loadNEWT(); + } + + public KDDisplay() { + } + + protected void createNative() { + // FIXME: map name to EGL_*_DISPLAY + long handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if (handle == EGL.EGL_NO_DISPLAY) { + throw new NativeWindowException("eglGetDisplay failed"); + } + if (!EGL.eglInitialize(handle, null, null)) { + throw new NativeWindowException("eglInitialize failed"); + } + aDevice = new EGLGraphicsDevice(handle); + } + + protected void closeNative() { + if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) { + EGL.eglTerminate(aDevice.getHandle()); + } + } +} + diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java new file mode 100755 index 000000000..752a55752 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDScreen.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.opengl.kd; + +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; + +public class KDScreen extends Screen { + public KDScreen() { + } + + protected void createNative(int index) { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + } + + protected void closeNative() { } + + // elevate access to this package .. + protected void setScreenSize(int w, int h) { + super.setScreenSize(w, h); + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java new file mode 100755 index 000000000..587bf185e --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/opengl/kd/KDWindow.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.opengl.kd; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import com.sun.opengl.impl.egl.*; +import javax.media.nativewindow.*; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.nativewindow.NativeWindowException; + +public class KDWindow extends Window { + private static final String WINDOW_CLASS_NAME = "NewtWindow"; + // non fullscreen dimensions .. + private int nfs_width, nfs_height, nfs_x, nfs_y; + + static { + NativeLibLoader.loadNEWT(); + + if (!initIDs()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + } + + public KDWindow() { + } + + protected void createNative(Capabilities caps) { + config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + GLCapabilities eglCaps = (GLCapabilities)config.getChosenCapabilities(); + int[] eglAttribs = EGLGraphicsConfiguration.GLCapabilities2AttribList(eglCaps, EGL.EGL_WINDOW_BIT); + + windowHandle = 0; + windowID = ++_windowID; + eglWindowHandle = CreateWindow(windowID, getDisplayHandle(), eglAttribs); + if (eglWindowHandle == 0) { + throw new NativeWindowException("Error creating egl window: "+config); + } + setVisible0(eglWindowHandle, false); + windowHandleClose = eglWindowHandle; + } + + protected void closeNative() { + if(0!=windowHandleClose) { + CloseWindow(windowHandleClose); + } + } + + public void setVisible(boolean visible) { + if(this.visible!=visible) { + this.visible=visible; + setVisible0(eglWindowHandle, visible); + if ( 0==windowHandle ) { + windowHandle = RealizeWindow(eglWindowHandle); + if (0 == windowHandle) { + throw new NativeWindowException("Error native Window Handle is null"); + } + } + clearEventMask(); + } + } + + public void setSize(int width, int height) { + setSize0(eglWindowHandle, width, height); + } + + public void setPosition(int x, int y) { + // n/a in KD + System.err.println("setPosition n/a in KD"); + } + + public boolean setFullscreen(boolean fullscreen) { + if(this.fullscreen!=fullscreen) { + this.fullscreen=fullscreen; + if(this.fullscreen) { + setFullScreen0(eglWindowHandle, true); + } else { + setFullScreen0(eglWindowHandle, false); + setSize0(eglWindowHandle, nfs_width, nfs_height); + } + } + return true; + } + + protected void dispatchMessages(int eventMask) { + DispatchMessages(windowID, eglWindowHandle, eventMask); + } + + //---------------------------------------------------------------------- + // Internals only + // + + private static native boolean initIDs(); + private native long CreateWindow(int owner, long displayHandle, int[] attributes); + private native long RealizeWindow(long eglWindowHandle); + private native int CloseWindow(long eglWindowHandle); + private native void setVisible0(long eglWindowHandle, boolean visible); + private native void setSize0(long eglWindowHandle, int width, int height); + private native void setFullScreen0(long eglWindowHandle, boolean fullscreen); + private native void DispatchMessages(int owner, long eglWindowHandle, int eventMask); + + private void sizeChanged(int newWidth, int newHeight) { + width = newWidth; + height = newHeight; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } else { + ((KDScreen)screen).setScreenSize(width, height); + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + } + + private long eglWindowHandle; + private long windowHandleClose; + private int windowID; + private static int _windowID = 0; +} diff --git a/src/newt/classes/com/sun/javafx/newt/util/MainThread.java b/src/newt/classes/com/sun/javafx/newt/util/MainThread.java new file mode 100644 index 000000000..01604476d --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/util/MainThread.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.sun.javafx.newt.util; + +import java.util.*; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +import javax.media.nativewindow.*; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import com.sun.javafx.newt.macosx.MacWindow; +import com.sun.nativewindow.impl.NWReflection; + +/** + * NEWT Utility class MainThread<P> + * + * This class provides a startup singleton <i>main thread</i>, + * from which a new thread with the users main class is launched.<br> + * + * Such behavior is necessary for native windowing toolkits, + * where the windowing management must happen on the so called + * <i>main thread</i> e.g. for Mac OS X !<br> + * + * Utilizing this class as a launchpad, now you are able to + * use a NEWT multithreaded application with window handling within the different threads, + * even on these restricted platforms.<br> + * + * To support your NEWT Window platform, + * you have to pass your <i>main thread</i> actions to {@link #invoke invoke(..)}, + * have a look at the {@link com.sun.javafx.newt.macosx.MacWindow MacWindow} implementation.<br> + * <i>TODO</i>: Some hardcoded dependencies exist in this implementation, + * where you have to patch this code or factor it out. <P> + * + * If your platform is not Mac OS X, but you want to test your code without modifying + * this class, you have to set the system property <code>newt.MainThread.force</code> to <code>true</code>.<P> + * + * The code is compatible with all other platform, which support multithreaded windowing handling. + * Since those platforms won't trigger the <i>main thread</i> serialization, the main method + * will be simply executed, in case you haven't set <code>newt.MainThread.force</code> to <code>true</code>.<P> + * + * Test case on Mac OS X (or any other platform): + <PRE> + java -XstartOnFirstThread com.sun.javafx.newt.util.MainThread demos.es1.RedSquare -GL2 -GL2 -GL2 -GL2 + </PRE> + * Which starts 4 threads, each with a window and OpenGL rendering.<br> + */ +public class MainThread { + public static final boolean USE_MAIN_THREAD = NativeWindowFactory.getNativeWindowType(false)==NativeWindowFactory.TYPE_MACOSX || + Boolean.getBoolean("newt.MainThread.force"); + + protected static final boolean DEBUG = Debug.debug("MainThread"); + + private static boolean isExit=false; + private static volatile boolean isRunning=false; + private static Object taskWorkerLock=new Object(); + private static boolean shouldStop; + private static ArrayList tasks; + private static ArrayList tasksBlock; + private static Thread mainThread; + + static class MainAction extends Thread { + private String mainClassName; + private String[] mainClassArgs; + + private Class mainClass; + private Method mainClassMain; + + public MainAction(String mainClassName, String[] mainClassArgs) { + this.mainClassName=mainClassName; + this.mainClassArgs=mainClassArgs; + } + + public void run() { + if ( USE_MAIN_THREAD ) { + // we have to start first to provide the service .. + MainThread.waitUntilRunning(); + } + + // start user app .. + try { + Class mainClass = NWReflection.getClass(mainClassName, true); + if(null==mainClass) { + throw new RuntimeException(new ClassNotFoundException("MainThread couldn't find main class "+mainClassName)); + } + try { + mainClassMain = mainClass.getDeclaredMethod("main", new Class[] { String[].class }); + mainClassMain.setAccessible(true); + } catch (Throwable t) { + throw new RuntimeException(t); + } + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName); + mainClassMain.invoke(null, new Object[] { mainClassArgs } ); + } catch (InvocationTargetException ite) { + ite.getTargetException().printStackTrace(); + } catch (Throwable t) { + t.printStackTrace(); + } + + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin"); + + if ( USE_MAIN_THREAD ) { + MainThread.exit(); + if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainThread fin - exit"); + System.exit(0); + } + } + } + private static MainAction mainAction; + + /** Your new java application main entry, which pipelines your application */ + public static void main(String[] args) { + if(DEBUG) System.err.println("MainThread.main(): "+Thread.currentThread().getName()+" USE_MAIN_THREAD "+ USE_MAIN_THREAD ); + + if(args.length==0) { + return; + } + + String mainClassName=args[0]; + String[] mainClassArgs=new String[args.length-1]; + if(args.length>1) { + System.arraycopy(args, 1, mainClassArgs, 0, args.length-1); + } + + NativeLibLoader.loadNEWT(); + + shouldStop = false; + tasks = new ArrayList(); + tasksBlock = new ArrayList(); + mainThread = Thread.currentThread(); + + mainAction = new MainAction(mainClassName, mainClassArgs); + + if(NativeWindowFactory.getNativeWindowType(false)==NativeWindowFactory.TYPE_MACOSX) { + MacWindow.initSingleton(); + } + + if ( USE_MAIN_THREAD ) { + // dispatch user's main thread .. + mainAction.start(); + + // do our main thread task scheduling + run(); + } else { + // run user's main in this thread + mainAction.run(); + } + } + + /** invokes the given Runnable */ + public static void invoke(boolean wait, Runnable r) { + if(r == null) { + return; + } + + // if this main thread is not being used or + // if this is already the main thread .. just execute. + if( !isRunning() || mainThread == Thread.currentThread() ) { + r.run(); + return; + } + + synchronized(taskWorkerLock) { + tasks.add(r); + if(wait) { + tasksBlock.add(r); + } + taskWorkerLock.notifyAll(); + if(wait) { + while(tasksBlock.size()>0) { + try { + taskWorkerLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + + public static void exit() { + if(DEBUG) System.err.println("MainThread.exit(): "+Thread.currentThread().getName()+" start"); + synchronized(taskWorkerLock) { + if(isRunning) { + shouldStop = true; + } + taskWorkerLock.notifyAll(); + } + if(DEBUG) System.err.println("MainThread.exit(): "+Thread.currentThread().getName()+" end"); + } + + public static boolean isRunning() { + synchronized(taskWorkerLock) { + return isRunning; + } + } + + private static void waitUntilRunning() { + synchronized(taskWorkerLock) { + if(isExit) return; + + while(!isRunning) { + try { + taskWorkerLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public static void run() { + if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName()); + synchronized(taskWorkerLock) { + isRunning = true; + taskWorkerLock.notifyAll(); + } + while(!shouldStop) { + try { + ArrayList localTasks=null; + + // wait for something todo .. + synchronized(taskWorkerLock) { + while(!shouldStop && tasks.size()==0) { + try { + taskWorkerLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + // seq. process all tasks until no blocking one exists in the list + for(Iterator i = tasks.iterator(); tasksBlock.size()>0 && i.hasNext(); ) { + Runnable task = (Runnable) i.next(); + task.run(); + i.remove(); + tasksBlock.remove(task); + } + + // take over the tasks .. + if(tasks.size()>0) { + localTasks = tasks; + tasks = new ArrayList(); + } + taskWorkerLock.notifyAll(); + } + + // seq. process all unblocking tasks .. + if(null!=localTasks) { + for(Iterator i = localTasks.iterator(); i.hasNext(); ) { + Runnable task = (Runnable) i.next(); + task.run(); + } + } + } catch (Throwable t) { + // handle errors .. + t.printStackTrace(); + } finally { + // epilog - unlock locked stuff + } + } + if(DEBUG) System.err.println("MainThread.run(): "+Thread.currentThread().getName()+" fin"); + synchronized(taskWorkerLock) { + isRunning = false; + isExit = true; + taskWorkerLock.notifyAll(); + } + } +} + + diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java new file mode 100755 index 000000000..436101a35 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsDisplay.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.windows; + +import com.sun.javafx.newt.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; + +public class WindowsDisplay extends Display { + public WindowsDisplay() { + } + + protected void createNative() { + aDevice = new WindowsGraphicsDevice(); + } + + protected void closeNative() { } +} diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java new file mode 100755 index 000000000..828cf4ca0 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsScreen.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.windows; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import javax.media.nativewindow.*; + +public class WindowsScreen extends Screen { + static { + NativeLibLoader.loadNEWT(); + } + + public WindowsScreen() { + } + + protected void createNative(int index) { + aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), index); + setScreenSize(getScreenWidth(getIndex()), getScreenHeight(getIndex())); + } + + protected void closeNative() { } + + private native int getScreenWidth(int scrn_idx); + private native int getScreenHeight(int scrn_idx); +} diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java new file mode 100755 index 000000000..273be6653 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.windows; + +import javax.media.nativewindow.*; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; + +public class WindowsWindow extends Window { + + private long hmon; + private long hdc; + private long windowHandleClose; + // non fullscreen dimensions .. + private int nfs_width, nfs_height, nfs_x, nfs_y; + + static { + NativeLibLoader.loadNEWT(); + + if (!initIDs()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + } + + public WindowsWindow() { + } + + public long getSurfaceHandle() { + if (hdc == 0) { + hdc = GetDC(windowHandle); + hmon = MonitorFromWindow(windowHandle); + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window new surface handle "+Thread.currentThread().getName()+ + ",HDC 0x"+Long.toHexString(hdc)+", HMON 0x"+Long.toHexString(hmon)); + e.printStackTrace(); + } + } + return hdc; + } + + public boolean hasDeviceChanged() { + long _hmon = MonitorFromWindow(windowHandle); + if (hmon != _hmon) { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window Device Changed "+Thread.currentThread().getName()+ + ", HMON 0x"+Long.toHexString(hmon)+" -> 0x"+Long.toHexString(_hmon)); + e.printStackTrace(); + } + hmon = _hmon; + return true; + } + return false; + } + + public void disposeSurfaceHandle() { + if (hdc != 0) { + ReleaseDC(windowHandle, hdc); + hdc=0; + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + Exception e = new Exception("!!! Window surface handle disposed "+Thread.currentThread().getName()); + e.printStackTrace(); + } + } + } + + protected void createNative(Capabilities caps) { + config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + windowHandle = CreateWindow(getWindowClassAtom(), WINDOW_CLASS_NAME, getHInstance(), 0, undecorated, x, y, width, height); + if (windowHandle == 0) { + throw new NativeWindowException("Error creating window"); + } + windowHandleClose = windowHandle; + } + + protected void closeNative() { + if (hdc != 0) { + if(windowHandleClose != 0) { + ReleaseDC(windowHandleClose, hdc); + } + hdc = 0; + } + if(windowHandleClose != 0) { + DestroyWindow(windowHandleClose); + windowHandleClose = 0; + } + } + + protected void windowDestroyed() { + // singleton ATOM CleanupWindowResources(getWindowClassAtom(), getHInstance()); + windowHandleClose = 0; + super.windowDestroyed(); + } + + public void setVisible(boolean visible) { + if(this.visible!=visible) { + this.visible=visible; + setVisible0(windowHandle, visible); + } + } + + // @Override + public void setSize(int width, int height) { + if (width != this.width || this.height != height) { + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + this.width = width; + this.height = height; + setSize0(windowHandle, width, height); + } + } + + //@Override + public void setPosition(int x, int y) { + if (this.x != x || this.y != y) { + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + this.x = x; + this.y = y; + setPosition(windowHandle, x , y); + } + } + + public boolean setFullscreen(boolean fullscreen) { + if(this.fullscreen!=fullscreen) { + int x,y,w,h; + this.fullscreen=fullscreen; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("WindowsWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + setFullscreen0(windowHandle, x, y, w, h, undecorated, fullscreen); + } + return fullscreen; + } + + // @Override + public void requestFocus() { + super.requestFocus(); + if (windowHandle != 0L) { + requestFocus(windowHandle); + } + } + + // @Override + public void setTitle(String title) { + if (title == null) { + title = ""; + } + if (!title.equals(getTitle())) { + super.setTitle(title); + setTitle(windowHandle, title); + } + } + + protected void dispatchMessages(int eventMask) { + DispatchMessages(windowHandle, eventMask); + } + + //---------------------------------------------------------------------- + // Internals only + // + private static final String WINDOW_CLASS_NAME = "NewtWindowClass"; + + private static int windowClassAtom = 0; + private static synchronized int getWindowClassAtom() { + if(0 == windowClassAtom) { + windowClassAtom = RegisterWindowClass(WINDOW_CLASS_NAME, getHInstance()); + if (windowClassAtom == 0) { + throw new NativeWindowException("Error while registering window class"); + } + } + return windowClassAtom; + } + private static long hInstance; + private static synchronized long getHInstance() { + if (hInstance == 0) { + hInstance = LoadLibraryW("newt"); + if (hInstance == 0) { + throw new NativeWindowException("Error finding HINSTANCE for \"newt\""); + } + } + return hInstance; + } + + private static native boolean initIDs(); + private static native long LoadLibraryW(String libraryName); + private static native int RegisterWindowClass(String windowClassName, long hInstance); + private native long CreateWindow(int wndClassAtom, String wndName, + long hInstance, long visualID, + boolean isUndecorated, + int x, int y, int width, int height); + private native void CleanupWindowResources(int wndClassAtom, long hInstance); + private native void DestroyWindow(long windowHandle); + private native long GetDC(long windowHandle); + private native void ReleaseDC(long windowHandle, long hdc); + private native long MonitorFromWindow(long windowHandle); + private static native void setVisible0(long windowHandle, boolean visible); + private static native void DispatchMessages(long windowHandle, int eventMask); + private native void setSize0(long windowHandle, int width, int height); + private native void setPosition(long windowHandle, int x, int y); + private native void setFullscreen0(long windowHandle, int x, int y, int width, int height, boolean isUndecorated, boolean on); + private static native void setTitle(long windowHandle, String title); + private static native void requestFocus(long windowHandle); + + private void sizeChanged(int newWidth, int newHeight) { + width = newWidth; + height = newHeight; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + } + + private void positionChanged(int newX, int newY) { + x = newX; + y = newY; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + } + + /** + * + * @param focusOwner if focusGained is true, focusOwner is the previous + * focus owner, if focusGained is false, focusOwner is the new focus owner + * @param focusGained + */ + private void focusChanged(long focusOwner, boolean focusGained) { + if (focusGained) { + sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); + } else { + sendWindowEvent(WindowEvent.EVENT_WINDOW_LOST_FOCUS); + } + } +} diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java new file mode 100755 index 000000000..2371b20e8 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Display.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.x11; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; + +public class X11Display extends Display { + static { + NativeLibLoader.loadNEWT(); + } + + public X11Display() { + } + + protected void createNative() { + long handle = CreateDisplay(name); + if (handle == 0 ) { + throw new RuntimeException("Error creating display: "+name); + } + aDevice = new X11GraphicsDevice(handle); + } + + protected void closeNative() { } + + //---------------------------------------------------------------------- + // Internals only + // + + private native long CreateDisplay(String name); +} diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java new file mode 100755 index 000000000..36d9d8baf --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Screen.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.x11; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; + +public class X11Screen extends Screen { + static { + NativeLibLoader.loadNEWT(); + } + + public X11Screen() { + } + + protected void createNative(int index) { + long handle = GetScreen(display.getHandle(), index); + if (handle == 0 ) { + throw new RuntimeException("Error creating screen: "+index); + } + aScreen = new X11GraphicsScreen((X11GraphicsDevice)getDisplay().getGraphicsDevice(), index); + setScreenSize(getWidth0(display.getHandle(), index), + getHeight0(display.getHandle(), index)); + } + + protected void closeNative() { } + + //---------------------------------------------------------------------- + // Internals only + // + + private native long GetScreen(long dpy, int scrn_idx); + private native int getWidth0(long display, int scrn_idx); + private native int getHeight0(long display, int scrn_idx); +} + diff --git a/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java b/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java new file mode 100755 index 000000000..3badcce16 --- /dev/null +++ b/src/newt/classes/com/sun/javafx/newt/x11/X11Window.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.sun.javafx.newt.x11; + +import com.sun.javafx.newt.*; +import com.sun.javafx.newt.impl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; + +public class X11Window extends Window { + private static final String WINDOW_CLASS_NAME = "NewtWindow"; + // non fullscreen dimensions .. + private int nfs_width, nfs_height, nfs_x, nfs_y; + + static { + NativeLibLoader.loadNEWT(); + + if (!initIDs()) { + throw new NativeWindowException("Failed to initialize jmethodIDs"); + } + } + + public X11Window() { + } + + protected void createNative(Capabilities caps) { + config = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice()).chooseGraphicsConfiguration(caps, null, getScreen().getGraphicsScreen()); + if (config == null) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; + long visualID = x11config.getVisualID(); + long w = CreateWindow(getDisplayHandle(), getScreenIndex(), visualID, x, y, width, height); + if (w == 0 || w!=windowHandle) { + throw new NativeWindowException("Error creating window: "+w); + } + windowHandleClose = windowHandle; + displayHandleClose = getDisplayHandle(); + } + + protected void closeNative() { + if(0!=displayHandleClose && 0!=windowHandleClose) { + CloseWindow(displayHandleClose, windowHandleClose); + windowHandleClose = 0; + displayHandleClose = 0; + } + } + + protected void windowDestroyed() { + windowHandleClose = 0; + displayHandleClose = 0; + super.windowDestroyed(); + } + + public void setVisible(boolean visible) { + if(this.visible!=visible) { + this.visible=visible; + setVisible0(getDisplayHandle(), windowHandle, visible); + clearEventMask(); + } + } + + public void setSize(int width, int height) { + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + setSize0(getDisplayHandle(), getScreenIndex(), windowHandle, x, y, width, height, 0, visible); + } + + public void setPosition(int x, int y) { + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + setPosition0(getDisplayHandle(), windowHandle, x, y); + } + + public boolean setFullscreen(boolean fullscreen) { + if(this.fullscreen!=fullscreen) { + int x,y,w,h; + this.fullscreen=fullscreen; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + setSize0(getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, fullscreen?-1:1, visible); + } + return fullscreen; + } + + protected void dispatchMessages(int eventMask) { + DispatchMessages(getDisplayHandle(), windowHandle, eventMask, windowDeleteAtom); + } + + //---------------------------------------------------------------------- + // Internals only + // + + private static native boolean initIDs(); + private native long CreateWindow(long display, int screen_index, + long visualID, int x, int y, int width, int height); + private native void CloseWindow(long display, long windowHandle); + private native void setVisible0(long display, long windowHandle, boolean visible); + private native void DispatchMessages(long display, long windowHandle, int eventMask, long windowDeleteAtom); + private native void setSize0(long display, int screen_index, long windowHandle, + int x, int y, int width, int height, int decorationToggle, boolean isVisible); + private native void setPosition0(long display, long windowHandle, int x, int y); + + private void sizeChanged(int newWidth, int newHeight) { + width = newWidth; + height = newHeight; + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); + } + + private void positionChanged(int newX, int newY) { + x = newX; + y = newY; + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + } + sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); + } + + private void windowCreated(long windowHandle, long windowDeleteAtom) { + this.windowHandle = windowHandle; + this.windowDeleteAtom=windowDeleteAtom; + } + + private long windowHandleClose; + private long displayHandleClose; + private long windowDeleteAtom; +} diff --git a/src/newt/native/EventListener.h b/src/newt/native/EventListener.h new file mode 100644 index 000000000..2e0e92323 --- /dev/null +++ b/src/newt/native/EventListener.h @@ -0,0 +1,9 @@ + +#ifndef _EVENT_LISTSENER_H +#define _EVENT_LISTSENER_H + +#define EVENT_WINDOW (1 << 0) +#define EVENT_MOUSE (1 << 1) +#define EVENT_KEY (1 << 2) + +#endif diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h new file mode 100644 index 000000000..b42c06d21 --- /dev/null +++ b/src/newt/native/InputEvent.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifndef _INPUT_EVENT_H_ +#define _INPUT_EVENT_H_ + +#define EVENT_SHIFT_MASK 1 +#define EVENT_CTRL_MASK 2 +#define EVENT_META_MASK 4 +#define EVENT_ALT_MASK 8 +#define EVENT_ALT_GRAPH_MASK 32 +#define EVENT_BUTTON1_MASK (1<<6) +#define EVENT_BUTTON2_MASK (1<<7) +#define EVENT_BUTTON3_MASK (1<<8) + +#endif diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c new file mode 100755 index 000000000..d08d5411c --- /dev/null +++ b/src/newt/native/KDWindow.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#ifdef _WIN32 + #include <windows.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +/* This typedef is apparently needed for Microsoft compilers before VC8, + and on Windows CE */ +#if (_MSC_VER < 1400) || defined(UNDER_CE) + #ifdef _WIN64 + typedef long long intptr_t; + #else + typedef int intptr_t; + #endif +#elif _MSC_VER <= 1500 + #ifdef _WIN64 // [ + typedef __int64 intptr_t; + #else // _WIN64 ][ + typedef int intptr_t; + #endif // _WIN64 ] +#else + #include <inttypes.h> +#endif + +#include <KD/kd.h> +#include <KD/NV_extwindowprops.h> + +#include "com_sun_javafx_newt_opengl_kd_KDWindow.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "KeyEvent.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(...) fprintf(stdout, __VA_ARGS__) +#else + #define DBG_PRINT(...) +#endif + +#ifdef VERBOSE_ON + #ifdef _WIN32_WCE + #define STDOUT_FILE "\\Storage Card\\stdout.txt" + #define STDERR_FILE "\\Storage Card\\stderr.txt" + #endif +#endif + +/** + * Window + */ + +static jmethodID sizeChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_kd_KDWindow_initIDs + (JNIEnv *env, jclass clazz) +{ +#ifdef VERBOSE_ON + #ifdef _WIN32_WCE + _wfreopen(TEXT(STDOUT_FILE),L"w",stdout); + _wfreopen(TEXT(STDERR_FILE),L"w",stderr); + #endif +#endif + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + windowDestroyNotifyID == NULL || + windowDestroyedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + DBG_PRINT( "initIDs failed\n" ); + return JNI_FALSE; + } + DBG_PRINT( "initIDs ok\n" ); + return JNI_TRUE; +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CreateWindow + (JNIEnv *env, jobject obj, jint owner, jlong display, jintArray jAttrs) +{ + jint * attrs = NULL; + jsize attrsLen; + EGLDisplay dpy = (EGLDisplay)(intptr_t)display; + KDWindow *window = 0; + + DBG_PRINT( "[CreateWindow]: owner %d\n", owner); + + if(dpy==NULL) { + fprintf(stderr, "[CreateWindow] invalid display connection..\n"); + return 0; + } + + attrsLen = (*env)->GetArrayLength(env, jAttrs); + if(0==attrsLen) { + fprintf(stderr, "[CreateWindow] attribute array size 0..\n"); + return 0; + } + attrs = (*env)->GetIntArrayElements(env, jAttrs, 0); + if(NULL==attrs) { + fprintf(stderr, "[CreateWindow] attribute array NULL..\n"); + return 0; + } + + /* passing the KDWindow instance for the eventuserptr */ + window = kdCreateWindow(dpy, attrs, (void *)(intptr_t)owner); + + (*env)->ReleaseIntArrayElements(env, jAttrs, attrs, 0); + + if(NULL==window) { + fprintf(stderr, "[CreateWindow] failed: 0x%X\n", kdGetError()); + } + DBG_PRINT( "[CreateWindow] ok: %p, owner %d\n", window, (void *)(intptr_t)owner); + return (jlong) (intptr_t) window; +} + +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_kd_KDWindow_RealizeWindow + (JNIEnv *env, jobject obj, jlong window) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + EGLNativeWindowType nativeWindow=0; + + jint res = kdRealizeWindow(w, &nativeWindow); + if(res) { + fprintf(stderr, "[RealizeWindow] failed: 0x%X, 0x%X\n", res, kdGetError()); + nativeWindow = NULL; + } + DBG_PRINT( "[RealizeWindow] ok: %p\n", nativeWindow); + return (jlong) (intptr_t) nativeWindow; +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_kd_KDWindow_CloseWindow + (JNIEnv *env, jobject obj, jlong window) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + int res = kdDestroyWindow(w); + + DBG_PRINT( "[CloseWindow] res: %d\n", res); + return res; +} + +/* + * Class: com_sun_javafx_newt_kd_KDWindow + * Method: setVisible0 + * Signature: (JJZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setVisible0 + (JNIEnv *env, jobject obj, jlong window, jboolean visible) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE; + kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v); + DBG_PRINT( "[setVisible] v=%d\n", visible); +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_DispatchMessages + (JNIEnv *env, jobject obj, jint owner, jlong window, jint eventMask) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + const KDEvent * evt; + + // Periodically take a break + while( NULL!=(evt=kdWaitEvent(0)) ) { + jint src_owner = (jint)(intptr_t)evt->userptr; + if(src_owner != owner) { + DBG_PRINT( "event unrelated: src: %d, caller: %d, evt type: 0x%X\n", src_owner, owner, evt->type); + continue; + } + DBG_PRINT( "[DispatchMessages]: caller %d, evt type: 0x%X\n", owner, evt->type); + + switch(evt->type) { + case KD_EVENT_INPUT_POINTER: + if( ! ( eventMask & EVENT_MOUSE ) ) { + DBG_PRINT( "event mouse ignored: src: %d\n", owner); + continue; + } + break; + /* + case KeyPress: + case KeyRelease: + if( ! ( eventMask & EVENT_KEY ) ) { + DBG_PRINT( "event key ignored: src: %d\n", owner); + continue; + } + break; + */ + case KD_EVENT_WINDOW_FOCUS: + case KD_EVENT_WINDOW_CLOSE: + case KD_EVENT_WINDOWPROPERTY_CHANGE: + case KD_EVENT_WINDOW_REDRAW: + if( ! ( eventMask & EVENT_WINDOW ) ) { + DBG_PRINT( "event window ignored: src: %d\n", owner); + continue; + } + break; + } + + // FIXME: support resize and window re-positioning events + + switch(evt->type) { + case KD_EVENT_WINDOW_FOCUS: + { + KDboolean hasFocus; + kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_FOCUS, &hasFocus); + DBG_PRINT( "event window focus : src: %d\n", owner); + } + break; + case KD_EVENT_WINDOW_CLOSE: + { + DBG_PRINT( "event window close : src: %d\n", owner); + (*env)->CallVoidMethod(env, obj, windowDestroyNotifyID); + // Called by Window.java: DestroyWindow(wnd); + // (*env)->CallVoidMethod(env, obj, windowDestroyedID); + } + break; + case KD_EVENT_WINDOWPROPERTY_CHANGE: + { + const KDEventWindowProperty* prop = &evt->data.windowproperty; + switch (prop->pname) { + case KD_WINDOWPROPERTY_SIZE: + { + KDint32 v[2]; + if(!kdGetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v)) { + DBG_PRINT( "event window size change : src: %d %dx%d\n", owner, v[0], v[1]); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) v[0], (jint) v[1]); + } else { + DBG_PRINT( "event window size change error: src: %d %dx%d\n", owner, v[0], v[1]); + } + } + break; + case KD_WINDOWPROPERTY_FOCUS: + DBG_PRINT( "event window focus: src: %d\n", owner); + break; + case KD_WINDOWPROPERTY_VISIBILITY: + { + KDboolean visible; + kdGetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &visible); + DBG_PRINT( "event window visibility: src: %d, v:%d\n", owner, visible); + } + break; + default: + break; + } + } + break; + case KD_EVENT_INPUT_POINTER: + { + const KDEventInputPointer* ptr = &(evt->data.inputpointer); + // button idx: evt->data.input.index + // pressed = ev->data.input.value.i + // time = ev->timestamp + if(KD_INPUT_POINTER_SELECT==ptr->index) { + DBG_PRINT( "event mouse click: src: %d, s:%d, (%d,%d)\n", owner, ptr->select, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, obj, sendMouseEventID, + (ptr->select==0) ? (jint) EVENT_MOUSE_RELEASED : (jint) EVENT_MOUSE_PRESSED, + (jint) 0, + (jint) ptr->x, (jint) ptr->y, 1, 0); + } else { + DBG_PRINT( "event mouse: src: %d, s:%d, i:0x%X (%d,%d)\n", owner, ptr->select, ptr->index, ptr->x, ptr->y); + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + 0, + (jint) ptr->x, (jint) ptr->y, 0, 0); + } + } + break; + } + } +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setFullScreen0 + (JNIEnv *env, jobject obj, jlong window, jboolean fullscreen) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDboolean v = fullscreen; + + int res = kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_FULLSCREEN_NV, &v); + DBG_PRINT( "[setFullScreen] v=%d, res=%d\n", fullscreen, res); + (void)res; +} + +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_kd_KDWindow_setSize0 + (JNIEnv *env, jobject obj, jlong window, jint width, jint height) +{ + KDWindow *w = (KDWindow*) (intptr_t) window; + KDint32 v[] = { width, height }; + + int res = kdSetWindowPropertyiv(w, KD_WINDOWPROPERTY_SIZE, v); + DBG_PRINT( "[setSize] v=%dx%d, res=%d\n", width, height, res); + (void)res; + + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + diff --git a/src/newt/native/KeyEvent.h b/src/newt/native/KeyEvent.h new file mode 100644 index 000000000..1ead0f5e8 --- /dev/null +++ b/src/newt/native/KeyEvent.h @@ -0,0 +1,200 @@ + +#ifndef _KEY_EVENT_H_ +#define _KEY_EVENT_H_ + +#define EVENT_KEY_PRESSED 300 +#define EVENT_KEY_RELEASED 301 +#define EVENT_KEY_TYPED 302 + +#define J_CHAR_UNDEFINED 0xFFFF; +#define J_VK_ENTER '\n' +#define J_VK_BACK_SPACE '\b' +#define J_VK_TAB '\t' +#define J_VK_CANCEL 0x03 +#define J_VK_CLEAR 0x0C +#define J_VK_SHIFT 0x10 +#define J_VK_CONTROL 0x11 +#define J_VK_ALT 0x12 +#define J_VK_PAUSE 0x13 +#define J_VK_CAPS_LOCK 0x14 +#define J_VK_ESCAPE 0x1B +#define J_VK_SPACE 0x20 +#define J_VK_PAGE_UP 0x21 +#define J_VK_PAGE_DOWN 0x22 +#define J_VK_END 0x23 +#define J_VK_HOME 0x24 +#define J_VK_LEFT 0x25 +#define J_VK_UP 0x26 +#define J_VK_RIGHT 0x27 +#define J_VK_DOWN 0x28 +#define J_VK_COMMA 0x2C +#define J_VK_MINUS 0x2D +#define J_VK_PERIOD 0x2E +#define J_VK_SLASH 0x2F +#define J_VK_0 0x30 +#define J_VK_1 0x31 +#define J_VK_2 0x32 +#define J_VK_3 0x33 +#define J_VK_4 0x34 +#define J_VK_5 0x35 +#define J_VK_6 0x36 +#define J_VK_7 0x37 +#define J_VK_8 0x38 +#define J_VK_9 0x39 +#define J_VK_SEMICOLON 0x3B +#define J_VK_EQUALS 0x3D +#define J_VK_A 0x41 +#define J_VK_B 0x42 +#define J_VK_C 0x43 +#define J_VK_D 0x44 +#define J_VK_E 0x45 +#define J_VK_F 0x46 +#define J_VK_G 0x47 +#define J_VK_H 0x48 +#define J_VK_I 0x49 +#define J_VK_J 0x4A +#define J_VK_K 0x4B +#define J_VK_L 0x4C +#define J_VK_M 0x4D +#define J_VK_N 0x4E +#define J_VK_O 0x4F +#define J_VK_P 0x50 +#define J_VK_Q 0x51 +#define J_VK_R 0x52 +#define J_VK_S 0x53 +#define J_VK_T 0x54 +#define J_VK_U 0x55 +#define J_VK_V 0x56 +#define J_VK_W 0x57 +#define J_VK_X 0x58 +#define J_VK_Y 0x59 +#define J_VK_Z 0x5A +#define J_VK_OPEN_BRACKET 0x5B +#define J_VK_BACK_SLASH 0x5C +#define J_VK_CLOSE_BRACKET 0x5D +#define J_VK_NUMPAD0 0x60 +#define J_VK_NUMPAD1 0x61 +#define J_VK_NUMPAD2 0x62 +#define J_VK_NUMPAD3 0x63 +#define J_VK_NUMPAD4 0x64 +#define J_VK_NUMPAD5 0x65 +#define J_VK_NUMPAD6 0x66 +#define J_VK_NUMPAD7 0x67 +#define J_VK_NUMPAD8 0x68 +#define J_VK_NUMPAD9 0x69 +#define J_VK_MULTIPLY 0x6A +#define J_VK_ADD 0x6B +#define J_VK_SEPARATOR 0x6C +#define J_VK_SUBTRACT 0x6D +#define J_VK_DECIMAL 0x6E +#define J_VK_DIVIDE 0x6F +#define J_VK_DELETE 0x7F /* ASCII DEL */ +#define J_VK_NUM_LOCK 0x90 +#define J_VK_SCROLL_LOCK 0x91 +#define J_VK_F1 0x70 +#define J_VK_F2 0x71 +#define J_VK_F3 0x72 +#define J_VK_F4 0x73 +#define J_VK_F5 0x74 +#define J_VK_F6 0x75 +#define J_VK_F7 0x76 +#define J_VK_F8 0x77 +#define J_VK_F9 0x78 +#define J_VK_F10 0x79 +#define J_VK_F11 0x7A +#define J_VK_F12 0x7B +#define J_VK_F13 0xF000 +#define J_VK_F14 0xF001 +#define J_VK_F15 0xF002 +#define J_VK_F16 0xF003 +#define J_VK_F17 0xF004 +#define J_VK_F18 0xF005 +#define J_VK_F19 0xF006 +#define J_VK_F20 0xF007 +#define J_VK_F21 0xF008 +#define J_VK_F22 0xF009 +#define J_VK_F23 0xF00A +#define J_VK_F24 0xF00B +#define J_VK_PRINTSCREEN 0x9A +#define J_VK_INSERT 0x9B +#define J_VK_HELP 0x9C +#define J_VK_META 0x9D +#define J_VK_BACK_QUOTE 0xC0 +#define J_VK_QUOTE 0xDE +#define J_VK_KP_UP 0xE0 +#define J_VK_KP_DOWN 0xE1 +#define J_VK_KP_LEFT 0xE2 +#define J_VK_KP_RIGHT 0xE3 +#define J_VK_DEAD_GRAVE 0x80 +#define J_VK_DEAD_ACUTE 0x81 +#define J_VK_DEAD_CIRCUMFLEX 0x82 +#define J_VK_DEAD_TILDE 0x83 +#define J_VK_DEAD_MACRON 0x84 +#define J_VK_DEAD_BREVE 0x85 +#define J_VK_DEAD_ABOVEDOT 0x86 +#define J_VK_DEAD_DIAERESIS 0x87 +#define J_VK_DEAD_ABOVERING 0x88 +#define J_VK_DEAD_DOUBLEACUTE 0x89 +#define J_VK_DEAD_CARON 0x8a +#define J_VK_DEAD_CEDILLA 0x8b +#define J_VK_DEAD_OGONEK 0x8c +#define J_VK_DEAD_IOTA 0x8d +#define J_VK_DEAD_VOICED_SOUND 0x8e +#define J_VK_DEAD_SEMIVOICED_SOUND 0x8f +#define J_VK_AMPERSAND 0x96 +#define J_VK_ASTERISK 0x97 +#define J_VK_QUOTEDBL 0x98 +#define J_VK_LESS 0x99 +#define J_VK_GREATER 0xa0 +#define J_VK_BRACELEFT 0xa1 +#define J_VK_BRACERIGHT 0xa2 +#define J_VK_AT 0x0200 +#define J_VK_COLON 0x0201 +#define J_VK_CIRCUMFLEX 0x0202 +#define J_VK_DOLLAR 0x0203 +#define J_VK_EURO_SIGN 0x0204 +#define J_VK_EXCLAMATION_MARK 0x0205 +#define J_VK_INVERTED_EXCLAMATION_MARK 0x0206 +#define J_VK_LEFT_PARENTHESIS 0x0207 +#define J_VK_NUMBER_SIGN 0x0208 +#define J_VK_PLUS 0x0209 +#define J_VK_RIGHT_PARENTHESIS 0x020A +#define J_VK_UNDERSCORE 0x020B +#define J_VK_WINDOWS 0x020C +#define J_VK_CONTEXT_MENU 0x020D +#define J_VK_FINAL 0x0018 +#define J_VK_CONVERT 0x001C +#define J_VK_NONCONVERT 0x001D +#define J_VK_ACCEPT 0x001E +#define J_VK_MODECHANGE 0x001F +#define J_VK_KANA 0x0015 +#define J_VK_KANJI 0x0019 +#define J_VK_ALPHANUMERIC 0x00F0 +#define J_VK_KATAKANA 0x00F1 +#define J_VK_HIRAGANA 0x00F2 +#define J_VK_FULL_WIDTH 0x00F3 +#define J_VK_HALF_WIDTH 0x00F4 +#define J_VK_ROMAN_CHARACTERS 0x00F5 +#define J_VK_ALL_CANDIDATES 0x0100 +#define J_VK_PREVIOUS_CANDIDATE 0x0101 +#define J_VK_CODE_INPUT 0x0102 +#define J_VK_JAPANESE_KATAKANA 0x0103 +#define J_VK_JAPANESE_HIRAGANA 0x0104 +#define J_VK_JAPANESE_ROMAN 0x0105 +#define J_VK_KANA_LOCK 0x0106 +#define J_VK_INPUT_METHOD_ON_OFF 0x0107 +#define J_VK_CUT 0xFFD1 +#define J_VK_COPY 0xFFCD +#define J_VK_PASTE 0xFFCF +#define J_VK_UNDO 0xFFCB +#define J_VK_AGAIN 0xFFC9 +#define J_VK_FIND 0xFFD0 +#define J_VK_PROPS 0xFFCA +#define J_VK_STOP 0xFFC8 +#define J_VK_COMPOSE 0xFF20 +#define J_VK_ALT_GRAPH 0xFF7E +#define J_VK_BEGIN 0xFF58 +#define J_VK_UNDEFINED 0x0 + +#endif + diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m new file mode 100644 index 000000000..f39a9f401 --- /dev/null +++ b/src/newt/native/MacWindow.m @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import <inttypes.h> + +#import "com_sun_javafx_newt_macosx_MacWindow.h" +#import "NewtMacWindow.h" + +#import "EventListener.h" +#import "MouseEvent.h" +#import "KeyEvent.h" + +#import <ApplicationServices/ApplicationServices.h> + +#import <stdio.h> + +NSString* jstringToNSString(JNIEnv* env, jstring jstr) +{ + const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL); + NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)]; + (*env)->ReleaseStringChars(env, jstr, jstrChars); + return str; +} + +void setFrameTopLeftPoint(NSWindow* win, jint x, jint y) +{ + NSScreen* screen = [NSScreen mainScreen]; + NSRect visibleScreenRect = [screen visibleFrame]; + NSPoint pt; + + pt = NSMakePoint(x, visibleScreenRect.origin.y + visibleScreenRect.size.height - y); + [win setFrameTopLeftPoint: pt]; +} + +static NewtView * changeContentView(JNIEnv *env, jobject javaWindowObject, NSWindow *win, NewtView *newView) { + NSView* oldNSView = [win contentView]; + NewtView* oldView = NULL; + + if(NULL!=oldNSView) { +NS_DURING + // Available >= 10.5 - Makes the menubar disapear + if([oldNSView isInFullScreenMode]) { + [oldNSView exitFullScreenModeWithOptions: NULL]; + } +NS_HANDLER +NS_ENDHANDLER + if( [oldNSView isMemberOfClass:[NewtView class]] ) { + oldView = (NewtView *) oldNSView; + + jobject globJavaWindowObject = [oldView getJavaWindowObject]; + (*env)->DeleteGlobalRef(env, globJavaWindowObject); + [oldView setJavaWindowObject: NULL]; + } + } + if(NULL!=newView) { + jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject); + [newView setJavaWindowObject: globJavaWindowObject]; + } + [win setContentView: newView]; + + return oldView; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + static int initialized = 0; + + if(initialized) return JNI_TRUE; + initialized = 1; + + // This little bit of magic is needed in order to receive mouse + // motion events and allow key focus to be properly transferred. + // FIXME: are these Carbon APIs? They come from the + // ApplicationServices.framework. + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); + } + + // Initialize the shared NSApplication instance + [NSApplication sharedApplication]; + + // Need this when debugging, as it is necessary to attach gdb to + // the running java process -- "gdb java" doesn't work + // printf("Going to sleep for 10 seconds\n"); + // sleep(10); + + return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: createWindow0 + * Signature: (IIIIZIIIJ)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_createWindow0 + (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, jboolean fullscreen, jint styleMask, + jint bufferingType, jint screen_idx, jlong jview) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSRect rect = NSMakeRect(x, y, w, h); + + 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]; + + if (fullscreen) { + styleMask = NSBorderlessWindowMask; + NSRect rect = [screen frame]; + w = (jint) (rect.size.width); + h = (jint) (rect.size.height); + } + + // Allocate the window + NSWindow* window = [[[NewtMacWindow alloc] initWithContentRect: rect + styleMask: (NSUInteger) styleMask + backing: (NSBackingStoreType) bufferingType + screen: screen] retain]; + + if (fullscreen) { + [window setOpaque: YES]; + } else { + // If the window is undecorated, assume we want the possibility of + // a shaped window, so make it non-opaque and the background color clear + if ((styleMask & NSTitledWindowMask) == 0) { + [window setOpaque: NO]; + [window setBackgroundColor: [NSColor clearColor]]; + } + } + + // Immediately re-position the window based on an upper-left coordinate system + setFrameTopLeftPoint(window, x, y); + + // specify we want mouse-moved events + [window setAcceptsMouseMovedEvents:YES]; + + // Use given NewtView or allocate an NewtView if NULL + NewtView* view = (0==jview)? [[NewtView alloc] initWithFrame: rect] : (NewtView*) ((intptr_t) jview) ; + + // Set the content view + (void) changeContentView(env, jthis, window, view); + +NS_DURING + // Available >= 10.5 - Makes the menubar disapear + if(fullscreen) { + [view enterFullScreenMode: screen withOptions:NULL]; + } +NS_HANDLER +NS_ENDHANDLER + + // Set the next responder to be the window so that we can forward + // right mouse button down events + [view setNextResponder: window]; + + [pool release]; + + return (jlong) ((intptr_t) window); +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: makeKeyAndOrderFront + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_makeKeyAndOrderFront + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win makeKeyAndOrderFront: win]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: makeKey + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_makeKey + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win makeKeyWindow]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: orderOut + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_orderOut + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win orderOut: win]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: close0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_close0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSView* view = [win contentView]; + [win orderOut: win]; +NS_DURING + if(NULL!=view) { + // Available >= 10.5 - Makes the menubar disapear + if([view isInFullScreenMode]) { + [view exitFullScreenModeWithOptions: NULL]; + } + } +NS_HANDLER +NS_ENDHANDLER + [win close]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setTitle0 + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setTitle0 + (JNIEnv *env, jobject unused, jlong window, jstring title) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSString* str = jstringToNSString(env, title); + [str autorelease]; + [win setTitle: str]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: dispatchMessages0 + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_dispatchMessages0 + (JNIEnv *env, jobject unused, jlong window, jint eventMask) +{ + NSEvent* event = NULL; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + +NS_DURING + + NSWindow* win = (NSWindow *) ((intptr_t) window); + + if(NULL != win) { + NewtView* view = (NewtView *) [win contentView]; + [view setJNIEnv: env]; + + do { + // FIXME: ignoring event mask for the time being + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantPast] + inMode: NSDefaultRunLoopMode + dequeue: YES]; + if (event != NULL) { + win = (NSWindow*) [event window]; + view = (NewtView *) [win contentView]; + [view setJNIEnv: env]; + + [NSApp sendEvent: event]; + } + } while (event != NULL); + } + +NS_HANDLER + + // just ignore it .. + +NS_ENDHANDLER + + + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: contentView + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_contentView + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + jlong res = (jlong) ((intptr_t) [win contentView]); + [pool release]; + return res; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: changeContentView + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_changeContentView + (JNIEnv *env, jobject jthis, jlong window, jlong jview) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NewtMacWindow*) ((intptr_t) window); + NewtView* newView = (NewtView *) ((intptr_t) jview); + + NewtView* oldView = changeContentView(env, jthis, win, newView); + + [pool release]; + + return oldView; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setContentSize + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setContentSize + (JNIEnv *env, jobject unused, jlong window, jint w, jint h) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSSize sz = NSMakeSize(w, h); + [win setContentSize: sz]; + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: setFrameTopLeftPoint + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_setFrameTopLeftPoint + (JNIEnv *env, jobject unused, jlong window, jint x, jint y) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + setFrameTopLeftPoint(win, x, y); + [pool release]; +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: getScreenWidth + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_getScreenWidth + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.width); +} + +/* + * Class: com_sun_javafx_newt_macosx_MacWindow + * Method: getScreenHeight + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_macosx_MacWindow_getScreenHeight + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.height); +} + diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h new file mode 100644 index 000000000..e9c0476ef --- /dev/null +++ b/src/newt/native/MouseEvent.h @@ -0,0 +1,15 @@ + +#ifndef _MOUSE_EVENT_H_ +#define _MOUSE_EVENT_H_ + +// Generated by Java: EVENT_MOUSE_CLICKED = 200; +#define EVENT_MOUSE_ENTERED 201 +#define EVENT_MOUSE_EXITED 202 +#define EVENT_MOUSE_PRESSED 203 +#define EVENT_MOUSE_RELEASED 204 +#define EVENT_MOUSE_MOVED 205 +// can't find how to regenerate this file, adding manually +#define EVENT_MOUSE_WHEEL_MOVED 207 +// Generated by Java: EVENT_MOUSE_DRAGGED = 206; + +#endif diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h new file mode 100644 index 000000000..09f9ffbd2 --- /dev/null +++ b/src/newt/native/NewtMacWindow.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import <AppKit/AppKit.h> +#import "jni.h" + +@interface NewtView : NSView +{ + jobject javaWindowObject; + + // This is set while messages are being dispatched and cleared afterward + JNIEnv* env; +} + +/* Set during event dispatching cycle */ +- (void) setJNIEnv: (JNIEnv*) env; +- (JNIEnv*) getJNIEnv; + +/* Register or deregister (NULL) the java Window object, + ie, if NULL, no events are send */ +- (void) setJavaWindowObject: (jobject) javaWindowObj; +- (jobject) getJavaWindowObject; + +- (void) rightMouseDown: (NSEvent*) theEvent; + +@end + +@interface NewtMacWindow : NSWindow +{ +} + ++ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (NSUInteger) windowStyle + backing: (NSBackingStoreType) bufferingType + screen:(NSScreen *)screen; + +@end diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m new file mode 100644 index 000000000..62c6a6e25 --- /dev/null +++ b/src/newt/native/NewtMacWindow.m @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import "NewtMacWindow.h" +#import "InputEvent.h" +#import "KeyEvent.h" +#import "MouseEvent.h" + +@implementation NewtView +- (void) setJNIEnv: (JNIEnv*) theEnv +{ + env = theEnv; +} +- (JNIEnv*) getJNIEnv +{ + return env; +} + +- (void) setJavaWindowObject: (jobject) javaWindowObj +{ + javaWindowObject = javaWindowObj; +} + +- (jobject) getJavaWindowObject +{ + return javaWindowObject; +} + +- (void) rightMouseDown: (NSEvent*) theEvent +{ + NSResponder* next = [self nextResponder]; + if (next != nil) { + [next rightMouseDown: theEvent]; + } +} +@end + +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID focusChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; + +@implementation NewtMacWindow + ++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz +{ + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + if (sendMouseEventID && sendKeyEventID && sizeChangedID && positionChangedID && focusChangedID && windowDestroyedID && windowDestroyNotifyID) { + return YES; + } + return NO; +} + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (NSUInteger) windowStyle + backing: (NSBackingStoreType) bufferingType + screen:(NSScreen *)screen +{ + id res = [super initWithContentRect: contentRect + styleMask: windowStyle + backing: bufferingType + defer: YES + screen: screen]; + // Why is this necessary? Without it we don't get any of the + // delegate methods like resizing and window movement. + [self setDelegate: self]; + return res; +} + +- (BOOL) canBecomeKeyWindow +{ + // Even if the window is borderless, we still want it to be able + // to become the key window to receive keyboard events + return YES; +} + +static jint mods2JavaMods(NSUInteger mods) +{ + int javaMods = 0; + if (mods & NSShiftKeyMask) { + javaMods |= EVENT_SHIFT_MASK; + } + if (mods & NSControlKeyMask) { + javaMods |= EVENT_CTRL_MASK; + } + if (mods & NSCommandKeyMask) { + javaMods |= EVENT_META_MASK; + } + if (mods & NSAlternateKeyMask) { + javaMods |= EVENT_ALT_MASK; + } + return javaMods; +} + +- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + int i; + jint keyCode = (jint) [event keyCode]; + NSString* chars = [event charactersIgnoringModifiers]; + int len = [chars length]; + jint javaMods = mods2JavaMods([event modifierFlags]); + + for (i = 0; i < len; i++) { + // Note: the key code in the NSEvent does not map to anything we can use + jchar keyChar = (jchar) [chars characterAtIndex: i]; + + (*env)->CallVoidMethod(env, javaWindowObject, sendKeyEventID, + evType, javaMods, keyCode, keyChar); + } +} + +- (void) keyDown: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED]; +} + +- (void) keyUp: (NSEvent*) theEvent +{ + [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED]; +} + +- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + jint javaMods = mods2JavaMods([event modifierFlags]); + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + // NSPoint location = [event locationInWindow]; + // The following computation improves the behavior of mouse drag + // events when they also affect the location of the window, but it + // still isn't perfect + NSPoint curLocation = [NSEvent mouseLocation]; + NSPoint location = NSMakePoint(curLocation.x - frameRect.origin.x, + curLocation.y - frameRect.origin.y); + + // convert to 1-based button number (or use zero if no button is involved) + jint javaButtonNum; + switch ([event type]) { + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSLeftMouseDragged: + javaButtonNum = 1; + break; + case NSRightMouseDown: + case NSRightMouseUp: + case NSRightMouseDragged: + javaButtonNum = 3; + break; + case NSOtherMouseDown: + case NSOtherMouseUp: + case NSOtherMouseDragged: + javaButtonNum = 2; + break; + default: + javaButtonNum = 0; + break; + } + + (*env)->CallVoidMethod(env, javaWindowObject, sendMouseEventID, + evType, javaMods, + (jint) location.x, + (jint) (contentRect.size.height - location.y), + javaButtonNum, 0); +} + +- (void) mouseEntered: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED]; +} + +- (void) mouseExited: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_EXITED]; +} + +- (void) mouseMoved: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) mouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) mouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) mouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) rightMouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) rightMouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) rightMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void) otherMouseDown: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_PRESSED]; +} + +- (void) otherMouseDragged: (NSEvent*) theEvent +{ + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_MOVED]; +} + +- (void) otherMouseUp: (NSEvent*) theEvent +{ + [self sendMouseEvent: theEvent eventType: EVENT_MOUSE_RELEASED]; +} + +- (void)windowDidResize: (NSNotification*) notification +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + + (*env)->CallVoidMethod(env, javaWindowObject, sizeChangedID, + (jint) contentRect.size.width, + (jint) contentRect.size.height); +} + +- (void)windowDidMove: (NSNotification*) notification +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + NSRect rect = [self frame]; + NSScreen* menuBarScreen = NULL; + NSScreen* screen = NULL; + NSRect screenRect; + NSPoint pt; + + // FIXME: unclear whether this works correctly in multiple monitor situations + screen = [self screen]; + screenRect = [screen visibleFrame]; + pt = NSMakePoint(rect.origin.x, screenRect.origin.y + screenRect.size.height - rect.origin.y - rect.size.height); + + (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, + (jint) pt.x, (jint) pt.y); +} + +- (void)windowWillClose: (NSNotification*) notification +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyNotifyID); + // Will be called by Window.java (*env)->CallVoidMethod(env, javaWindowObject, windowDestroyedID); + + // EOL .. + (*env)->DeleteGlobalRef(env, javaWindowObject); + [view setJavaWindowObject: NULL]; +} + +- (void) windowDidBecomeKey: (NSNotification *) notification +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_TRUE); +} + +- (void) windowDidResignKey: (NSNotification *) notification +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + JNIEnv* env = [view getJNIEnv]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE); +} + +@end diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c new file mode 100755 index 000000000..f609de08d --- /dev/null +++ b/src/newt/native/WindowsWindow.c @@ -0,0 +1,1197 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include <Windows.h> +#include <Windowsx.h> +#include <tchar.h> +#include <stdlib.h> +// NOTE: it looks like SHFullScreen and/or aygshell.dll is not available on the APX 2500 any more +// #ifdef UNDER_CE +// #include "aygshell.h" +// #endif + +/* This typedef is apparently needed for Microsoft compilers before VC8, + and on Windows CE */ +#if (_MSC_VER < 1400) || defined(UNDER_CE) + #ifdef _WIN64 + typedef long long intptr_t; + #else + typedef int intptr_t; + #endif +#elif _MSC_VER <= 1500 + #ifdef _WIN64 // [ + typedef __int64 intptr_t; + #else // _WIN64 ][ + typedef int intptr_t; + #endif // _WIN64 ] +#else + #include <inttypes.h> +#endif + +#if _MSC_VER <= 1500 + // FIXME: Determine for which MSVC versions .. + #define strdup(s) _strdup(s) +#endif + +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x020A +#endif //WM_MOUSEWHEEL + +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 +#endif //WHEEL_DELTA + +#ifndef WHEEL_PAGESCROLL +#define WHEEL_PAGESCROLL (UINT_MAX) +#endif //WHEEL_PAGESCROLL + +#ifndef GET_WHEEL_DELTA_WPARAM // defined for (_WIN32_WINNT >= 0x0500) +#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam)) +#endif + +#ifndef MONITOR_DEFAULTTONULL +#define MONITOR_DEFAULTTONULL 0 +#endif +#ifndef MONITOR_DEFAULTTOPRIMARY +#define MONITOR_DEFAULTTOPRIMARY 1 +#endif +#ifndef MONITOR_DEFAULTTONEAREST +#define MONITOR_DEFAULTTONEAREST 2 +#endif + +#include "com_sun_javafx_newt_windows_WindowsWindow.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "InputEvent.h" +#include "KeyEvent.h" + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID focusChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +typedef struct { + JNIEnv* jenv; + jobject jinstance; +} WindowUserData; + +typedef struct { + UINT javaKey; + UINT windowsKey; +} KeyMapEntry; + +// Static table, arranged more or less spatially. +static KeyMapEntry keyMapTable[] = { + // Modifier keys + {J_VK_CAPS_LOCK, VK_CAPITAL}, + {J_VK_SHIFT, VK_SHIFT}, + {J_VK_CONTROL, VK_CONTROL}, + {J_VK_ALT, VK_MENU}, + {J_VK_NUM_LOCK, VK_NUMLOCK}, + + // Miscellaneous Windows keys + {J_VK_WINDOWS, VK_LWIN}, + {J_VK_WINDOWS, VK_RWIN}, + {J_VK_CONTEXT_MENU, VK_APPS}, + + // Alphabet + {J_VK_A, 'A'}, + {J_VK_B, 'B'}, + {J_VK_C, 'C'}, + {J_VK_D, 'D'}, + {J_VK_E, 'E'}, + {J_VK_F, 'F'}, + {J_VK_G, 'G'}, + {J_VK_H, 'H'}, + {J_VK_I, 'I'}, + {J_VK_J, 'J'}, + {J_VK_K, 'K'}, + {J_VK_L, 'L'}, + {J_VK_M, 'M'}, + {J_VK_N, 'N'}, + {J_VK_O, 'O'}, + {J_VK_P, 'P'}, + {J_VK_Q, 'Q'}, + {J_VK_R, 'R'}, + {J_VK_S, 'S'}, + {J_VK_T, 'T'}, + {J_VK_U, 'U'}, + {J_VK_V, 'V'}, + {J_VK_W, 'W'}, + {J_VK_X, 'X'}, + {J_VK_Y, 'Y'}, + {J_VK_Z, 'Z'}, + {J_VK_0, '0'}, + {J_VK_1, '1'}, + {J_VK_2, '2'}, + {J_VK_3, '3'}, + {J_VK_4, '4'}, + {J_VK_5, '5'}, + {J_VK_6, '6'}, + {J_VK_7, '7'}, + {J_VK_8, '8'}, + {J_VK_9, '9'}, + {J_VK_ENTER, VK_RETURN}, + {J_VK_SPACE, VK_SPACE}, + {J_VK_BACK_SPACE, VK_BACK}, + {J_VK_TAB, VK_TAB}, + {J_VK_ESCAPE, VK_ESCAPE}, + {J_VK_INSERT, VK_INSERT}, + {J_VK_DELETE, VK_DELETE}, + {J_VK_HOME, VK_HOME}, + {J_VK_END, VK_END}, + {J_VK_PAGE_UP, VK_PRIOR}, + {J_VK_PAGE_DOWN, VK_NEXT}, + {J_VK_CLEAR, VK_CLEAR}, // NumPad 5 + + // NumPad with NumLock off & extended arrows block (triangular) + {J_VK_LEFT, VK_LEFT}, + {J_VK_RIGHT, VK_RIGHT}, + {J_VK_UP, VK_UP}, + {J_VK_DOWN, VK_DOWN}, + + // NumPad with NumLock on: numbers + {J_VK_NUMPAD0, VK_NUMPAD0}, + {J_VK_NUMPAD1, VK_NUMPAD1}, + {J_VK_NUMPAD2, VK_NUMPAD2}, + {J_VK_NUMPAD3, VK_NUMPAD3}, + {J_VK_NUMPAD4, VK_NUMPAD4}, + {J_VK_NUMPAD5, VK_NUMPAD5}, + {J_VK_NUMPAD6, VK_NUMPAD6}, + {J_VK_NUMPAD7, VK_NUMPAD7}, + {J_VK_NUMPAD8, VK_NUMPAD8}, + {J_VK_NUMPAD9, VK_NUMPAD9}, + + // NumPad with NumLock on + {J_VK_MULTIPLY, VK_MULTIPLY}, + {J_VK_ADD, VK_ADD}, + {J_VK_SEPARATOR, VK_SEPARATOR}, + {J_VK_SUBTRACT, VK_SUBTRACT}, + {J_VK_DECIMAL, VK_DECIMAL}, + {J_VK_DIVIDE, VK_DIVIDE}, + + // Functional keys + {J_VK_F1, VK_F1}, + {J_VK_F2, VK_F2}, + {J_VK_F3, VK_F3}, + {J_VK_F4, VK_F4}, + {J_VK_F5, VK_F5}, + {J_VK_F6, VK_F6}, + {J_VK_F7, VK_F7}, + {J_VK_F8, VK_F8}, + {J_VK_F9, VK_F9}, + {J_VK_F10, VK_F10}, + {J_VK_F11, VK_F11}, + {J_VK_F12, VK_F12}, + {J_VK_F13, VK_F13}, + {J_VK_F14, VK_F14}, + {J_VK_F15, VK_F15}, + {J_VK_F16, VK_F16}, + {J_VK_F17, VK_F17}, + {J_VK_F18, VK_F18}, + {J_VK_F19, VK_F19}, + {J_VK_F20, VK_F20}, + {J_VK_F21, VK_F21}, + {J_VK_F22, VK_F22}, + {J_VK_F23, VK_F23}, + {J_VK_F24, VK_F24}, + + {J_VK_PRINTSCREEN, VK_SNAPSHOT}, + {J_VK_SCROLL_LOCK, VK_SCROLL}, + {J_VK_PAUSE, VK_PAUSE}, + {J_VK_CANCEL, VK_CANCEL}, + {J_VK_HELP, VK_HELP}, + + // Japanese +/* + {J_VK_CONVERT, VK_CONVERT}, + {J_VK_NONCONVERT, VK_NONCONVERT}, + {J_VK_INPUT_METHOD_ON_OFF, VK_KANJI}, + {J_VK_ALPHANUMERIC, VK_DBE_ALPHANUMERIC}, + {J_VK_KATAKANA, VK_DBE_KATAKANA}, + {J_VK_HIRAGANA, VK_DBE_HIRAGANA}, + {J_VK_FULL_WIDTH, VK_DBE_DBCSCHAR}, + {J_VK_HALF_WIDTH, VK_DBE_SBCSCHAR}, + {J_VK_ROMAN_CHARACTERS, VK_DBE_ROMAN}, +*/ + + {J_VK_UNDEFINED, 0} +}; + +/* +Dynamic mapping table for OEM VK codes. This table is refilled +by BuildDynamicKeyMapTable when keyboard layout is switched. +(see NT4 DDK src/input/inc/vkoem.h for OEM VK_ values). +*/ +typedef struct { + // OEM VK codes known in advance + UINT windowsKey; + // depends on input langauge (kbd layout) + UINT javaKey; +} DynamicKeyMapEntry; + +static DynamicKeyMapEntry dynamicKeyMapTable[] = { + {0x00BA, J_VK_UNDEFINED}, // VK_OEM_1 + {0x00BB, J_VK_UNDEFINED}, // VK_OEM_PLUS + {0x00BC, J_VK_UNDEFINED}, // VK_OEM_COMMA + {0x00BD, J_VK_UNDEFINED}, // VK_OEM_MINUS + {0x00BE, J_VK_UNDEFINED}, // VK_OEM_PERIOD + {0x00BF, J_VK_UNDEFINED}, // VK_OEM_2 + {0x00C0, J_VK_UNDEFINED}, // VK_OEM_3 + {0x00DB, J_VK_UNDEFINED}, // VK_OEM_4 + {0x00DC, J_VK_UNDEFINED}, // VK_OEM_5 + {0x00DD, J_VK_UNDEFINED}, // VK_OEM_6 + {0x00DE, J_VK_UNDEFINED}, // VK_OEM_7 + {0x00DF, J_VK_UNDEFINED}, // VK_OEM_8 + {0x00E2, J_VK_UNDEFINED}, // VK_OEM_102 + {0, 0} +}; + +// Auxiliary tables used to fill the above dynamic table. We first +// find the character for the OEM VK code using ::MapVirtualKey and +// then go through these auxiliary tables to map it to Java VK code. + +typedef struct { + WCHAR c; + UINT javaKey; +} CharToVKEntry; + +static const CharToVKEntry charToVKTable[] = { + {L'!', J_VK_EXCLAMATION_MARK}, + {L'"', J_VK_QUOTEDBL}, + {L'#', J_VK_NUMBER_SIGN}, + {L'$', J_VK_DOLLAR}, + {L'&', J_VK_AMPERSAND}, + {L'\'', J_VK_QUOTE}, + {L'(', J_VK_LEFT_PARENTHESIS}, + {L')', J_VK_RIGHT_PARENTHESIS}, + {L'*', J_VK_ASTERISK}, + {L'+', J_VK_PLUS}, + {L',', J_VK_COMMA}, + {L'-', J_VK_MINUS}, + {L'.', J_VK_PERIOD}, + {L'/', J_VK_SLASH}, + {L':', J_VK_COLON}, + {L';', J_VK_SEMICOLON}, + {L'<', J_VK_LESS}, + {L'=', J_VK_EQUALS}, + {L'>', J_VK_GREATER}, + {L'@', J_VK_AT}, + {L'[', J_VK_OPEN_BRACKET}, + {L'\\', J_VK_BACK_SLASH}, + {L']', J_VK_CLOSE_BRACKET}, + {L'^', J_VK_CIRCUMFLEX}, + {L'_', J_VK_UNDERSCORE}, + {L'`', J_VK_BACK_QUOTE}, + {L'{', J_VK_BRACELEFT}, + {L'}', J_VK_BRACERIGHT}, + {0x00A1, J_VK_INVERTED_EXCLAMATION_MARK}, + {0x20A0, J_VK_EURO_SIGN}, // ???? + {0,0} +}; + +// For dead accents some layouts return ASCII punctuation, while some +// return spacing accent chars, so both should be listed. NB: MS docs +// say that conversion routings return spacing accent character, not +// combining. +static const CharToVKEntry charToDeadVKTable[] = { + {L'`', J_VK_DEAD_GRAVE}, + {L'\'', J_VK_DEAD_ACUTE}, + {0x00B4, J_VK_DEAD_ACUTE}, + {L'^', J_VK_DEAD_CIRCUMFLEX}, + {L'~', J_VK_DEAD_TILDE}, + {0x02DC, J_VK_DEAD_TILDE}, + {0x00AF, J_VK_DEAD_MACRON}, + {0x02D8, J_VK_DEAD_BREVE}, + {0x02D9, J_VK_DEAD_ABOVEDOT}, + {L'"', J_VK_DEAD_DIAERESIS}, + {0x00A8, J_VK_DEAD_DIAERESIS}, + {0x02DA, J_VK_DEAD_ABOVERING}, + {0x02DD, J_VK_DEAD_DOUBLEACUTE}, + {0x02C7, J_VK_DEAD_CARON}, // aka hacek + {L',', J_VK_DEAD_CEDILLA}, + {0x00B8, J_VK_DEAD_CEDILLA}, + {0x02DB, J_VK_DEAD_OGONEK}, + {0x037A, J_VK_DEAD_IOTA}, // ASCII ??? + {0x309B, J_VK_DEAD_VOICED_SOUND}, + {0x309C, J_VK_DEAD_SEMIVOICED_SOUND}, + {0,0} +}; + +// ANSI CP identifiers are no longer than this +#define MAX_ACP_STR_LEN 7 + +static void BuildDynamicKeyMapTable() +{ + HKL hkl = GetKeyboardLayout(0); + // Will need this to reset layout after dead keys. + UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl); + DynamicKeyMapEntry *dynamic; + + LANGID idLang = LOWORD(GetKeyboardLayout(0)); + UINT codePage; + TCHAR strCodePage[MAX_ACP_STR_LEN]; + // use the LANGID to create a LCID + LCID idLocale = MAKELCID(idLang, SORT_DEFAULT); + // get the ANSI code page associated with this locale + if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, + strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 ) + { + codePage = _ttoi(strCodePage); + } else { + codePage = GetACP(); + } + + // Entries in dynamic table that maps between Java VK and Windows + // VK are built in three steps: + // 1. Map windows VK to ANSI character (cannot map to unicode + // directly, since ::ToUnicode is not implemented on win9x) + // 2. Convert ANSI char to Unicode char + // 3. Map Unicode char to Java VK via two auxilary tables. + + for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic) + { + char cbuf[2] = { '\0', '\0'}; + WCHAR ucbuf[2] = { L'\0', L'\0' }; + int nchars; + UINT scancode; + const CharToVKEntry *charMap; + int nconverted; + WCHAR uc; + BYTE kbdState[256]; + + // Defaults to J_VK_UNDEFINED + dynamic->javaKey = J_VK_UNDEFINED; + + GetKeyboardState(kbdState); + + kbdState[dynamic->windowsKey] |= 0x80; // Press the key. + + // Unpress modifiers, since they are most likely pressed as + // part of the keyboard switching shortcut. + kbdState[VK_CONTROL] &= ~0x80; + kbdState[VK_SHIFT] &= ~0x80; + kbdState[VK_MENU] &= ~0x80; + + scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl); + nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState, + (WORD*)cbuf, 0, hkl); + + // Auxiliary table used to map Unicode character to Java VK. + // Will assign a different table for dead keys (below). + charMap = charToVKTable; + + if (nchars < 0) { // Dead key + char junkbuf[2] = { '\0', '\0'}; + // Use a different table for dead chars since different layouts + // return different characters for the same dead key. + charMap = charToDeadVKTable; + + // We also need to reset layout so that next translation + // is unaffected by the dead status. We do this by + // translating <SPACE> key. + kbdState[dynamic->windowsKey] &= ~0x80; + kbdState[VK_SPACE] |= 0x80; + + ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, + (WORD*)junkbuf, 0, hkl); + } + + nconverted = MultiByteToWideChar(codePage, 0, + cbuf, 1, ucbuf, 2); + + uc = ucbuf[0]; + { + const CharToVKEntry *map; + for (map = charMap; map->c != 0; ++map) { + if (uc == map->c) { + dynamic->javaKey = map->javaKey; + break; + } + } + } + + } // for each VK_OEM_* +} + +// Really need to factor this out in to a separate run-time file +static jchar* GetNullTerminatedStringChars(JNIEnv* env, jstring str) +{ + jchar* strChars = NULL; + strChars = calloc((*env)->GetStringLength(env, str) + 1, sizeof(jchar)); + if (strChars != NULL) { + (*env)->GetStringRegion(env, str, 0, (*env)->GetStringLength(env, str), strChars); + } + return strChars; +} + +static jint GetModifiers() { + jint modifiers = 0; + if (HIBYTE(GetKeyState(VK_CONTROL)) != 0) { + modifiers |= EVENT_CTRL_MASK; + } + if (HIBYTE(GetKeyState(VK_SHIFT)) != 0) { + modifiers |= EVENT_SHIFT_MASK; + } + if (HIBYTE(GetKeyState(VK_MENU)) != 0) { + modifiers |= EVENT_ALT_MASK; + } + if (HIBYTE(GetKeyState(VK_LBUTTON)) != 0) { + modifiers |= EVENT_BUTTON1_MASK; + } + if (HIBYTE(GetKeyState(VK_MBUTTON)) != 0) { + modifiers |= EVENT_BUTTON2_MASK; + } + if (HIBYTE(GetKeyState(VK_RBUTTON)) != 0) { + modifiers |= EVENT_BUTTON3_MASK; + } + + return modifiers; +} + +static int WmChar(JNIEnv *env, jobject window, UINT character, UINT repCnt, + UINT flags, BOOL system) +{ + // The Alt modifier is reported in the 29th bit of the lParam, + // i.e., it is the 13th bit of `flags' (which is HIWORD(lParam)). + BOOL alt_is_down = (flags & (1<<13)) != 0; + if (system && alt_is_down) { + if (character == VK_SPACE) { + return 1; + } + } + + if (character == VK_RETURN) { + character = J_VK_ENTER; + } + (*env)->CallVoidMethod(env, window, sendKeyEventID, + (jint) EVENT_KEY_TYPED, + GetModifiers(), + (jint) -1, + (jchar) character); + return 1; +} + +UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers) +{ + int i, j; + // for the general case, use a bi-directional table + for (i = 0; keyMapTable[i].windowsKey != 0; i++) { + if (keyMapTable[i].windowsKey == windowsKey) { + return keyMapTable[i].javaKey; + } + } + for (j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) { + if (dynamicKeyMapTable[j].windowsKey == windowsKey) { + if (dynamicKeyMapTable[j].javaKey != J_VK_UNDEFINED) { + return dynamicKeyMapTable[j].javaKey; + } else { + break; + } + } + } + + return J_VK_UNDEFINED; +} + +static int WmKeyDown(JNIEnv *env, jobject window, UINT wkey, UINT repCnt, + UINT flags, BOOL system) +{ + UINT modifiers = 0, jkey = 0, character = -1; + if (wkey == VK_PROCESSKEY) { + return 1; + } + + modifiers = GetModifiers(); + jkey = WindowsKeyToJavaKey(wkey, modifiers); + +/* + character = WindowsKeyToJavaChar(wkey, modifiers, SAVE); +*/ + + (*env)->CallVoidMethod(env, window, sendKeyEventID, + (jint) EVENT_KEY_PRESSED, + modifiers, + (jint) jkey, + (jchar) character); + + /* windows does not create a WM_CHAR for the Del key + for some reason, so we need to create the KEY_TYPED event on the + WM_KEYDOWN. + */ + if (jkey == J_VK_DELETE) { + (*env)->CallVoidMethod(env, window, sendKeyEventID, + (jint) EVENT_KEY_TYPED, + GetModifiers(), + (jint) -1, + (jchar) '\177'); + } + + return 0; +} + +static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt, + UINT flags, BOOL system) +{ + UINT modifiers = 0, jkey = 0, character = -1; + if (wkey == VK_PROCESSKEY) { + return 1; + } + + modifiers = GetModifiers(); + jkey = WindowsKeyToJavaKey(wkey, modifiers); +/* + character = WindowsKeyToJavaChar(wkey, modifiers, SAVE); +*/ + + (*env)->CallVoidMethod(env, window, sendKeyEventID, + (jint) EVENT_KEY_RELEASED, + modifiers, + (jint) jkey, + (jchar) character); + + return 0; +} + +static LRESULT CALLBACK wndProc(HWND wnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + RECT rc; + int useDefWindowProc = 0; + JNIEnv *env = NULL; + jobject window = NULL; + BOOL isKeyDown = FALSE; + WindowUserData * wud; + +#if defined(UNDER_CE) || _MSC_VER <= 1200 + wud = (WindowUserData *) GetWindowLong(wnd, GWL_USERDATA); +#else + wud = (WindowUserData *) GetWindowLongPtr(wnd, GWLP_USERDATA); +#endif + if(NULL==wud) { + return DefWindowProc(wnd, message, wParam, lParam); + } + env = wud->jenv; + window = wud->jinstance; + + if (NULL==window || NULL==env) { + return DefWindowProc(wnd, message, wParam, lParam); + } + + switch (message) { + + // + // The signal pipeline for destruction is: + // Java::DestroyWindow(wnd) _or_ window-close-button -> + // WM_CLOSE -> Java::windowDestroyNotify -> W_DESTROY -> Java::windowDestroyed -> + // Java::CleanupWindowResources() + case WM_CLOSE: + (*env)->CallVoidMethod(env, window, windowDestroyNotifyID); + break; + + case WM_DESTROY: + { +#if defined(UNDER_CE) || _MSC_VER <= 1200 + SetWindowLong(wnd, GWL_USERDATA, NULL); +#else + SetWindowLongPtr(wnd, GWLP_USERDATA, NULL); +#endif + free(wud); wud=NULL; + (*env)->CallVoidMethod(env, window, windowDestroyedID); + (*env)->DeleteGlobalRef(env, window); + } + break; + + case WM_SYSCHAR: + useDefWindowProc = WmChar(env, window, wParam, + LOWORD(lParam), HIWORD(lParam), FALSE); + break; + + case WM_CHAR: + useDefWindowProc = WmChar(env, window, wParam, + LOWORD(lParam), HIWORD(lParam), TRUE); + break; + + case WM_KEYDOWN: + useDefWindowProc = WmKeyDown(env, window, wParam, + LOWORD(lParam), HIWORD(lParam), FALSE); + break; + + case WM_KEYUP: + useDefWindowProc = WmKeyUp(env, window, wParam, + LOWORD(lParam), HIWORD(lParam), FALSE); + break; + + case WM_SIZE: + GetClientRect(wnd, &rc); + (*env)->CallVoidMethod(env, window, sizeChangedID, (jint) rc.right, (jint) rc.bottom); + break; + + case WM_LBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_PRESSED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 1, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_LBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_RELEASED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 1, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_MBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_PRESSED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 2, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_MBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_RELEASED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 2, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_RBUTTONDOWN: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_PRESSED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 3, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_RBUTTONUP: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_RELEASED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 3, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_MOUSEMOVE: + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_MOVED, + GetModifiers(), + (jint) LOWORD(lParam), (jint) HIWORD(lParam), + (jint) 0, (jint) 0); + useDefWindowProc = 1; + break; + + case WM_MOUSEWHEEL: { + // need to convert the coordinates to component-relative + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + POINT eventPt; + eventPt.x = x; + eventPt.y = y; + ScreenToClient(wnd, &eventPt); + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jint) EVENT_MOUSE_WHEEL_MOVED, + GetModifiers(), + (jint) eventPt.x, (jint) eventPt.y, + (jint) 0, (jint) GET_WHEEL_DELTA_WPARAM(wParam)); + useDefWindowProc = 1; + break; + } + + case WM_SETFOCUS: + (*env)->CallVoidMethod(env, window, focusChangedID, + (jlong)wParam, JNI_TRUE); + useDefWindowProc = 1; + break; + + case WM_KILLFOCUS: + (*env)->CallVoidMethod(env, window, focusChangedID, + (jlong)wParam, JNI_FALSE); + useDefWindowProc = 1; + break; + + case WM_MOVE: + (*env)->CallVoidMethod(env, window, positionChangedID, + (jint)LOWORD(lParam), (jint)HIWORD(lParam)); + useDefWindowProc = 1; + break; + + case WM_ERASEBKGND: + // ignore erase background + useDefWindowProc = 0; + break; + + + // FIXME: generate EVENT_MOUSE_ENTERED, EVENT_MOUSE_EXITED + default: + useDefWindowProc = 1; + } + + if (useDefWindowProc) + return DefWindowProc(wnd, message, wParam, lParam); + return 0; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsScreen + * Method: getScreenWidth + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getScreenWidth + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + return (jint)GetSystemMetrics(SM_CXSCREEN); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsScreen + * Method: getScreenWidth + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsScreen_getScreenHeight + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + return (jint)GetSystemMetrics(SM_CYSCREEN); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initIDs + (JNIEnv *env, jclass clazz) +{ + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + positionChangedID == NULL || + focusChangedID == NULL || + windowDestroyNotifyID == NULL || + windowDestroyedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + return JNI_FALSE; + } + BuildDynamicKeyMapTable(); + return JNI_TRUE; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: LoadLibraryW + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_LoadLibraryW + (JNIEnv *env, jclass clazz, jstring dllName) +{ + jchar* _dllName = GetNullTerminatedStringChars(env, dllName); + HMODULE lib = LoadLibraryW(_dllName); + free(_dllName); + return (jlong) (intptr_t) lib; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: RegisterWindowClass + * Signature: (Ljava/lang/String;J)I + */ +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_RegisterWindowClass + (JNIEnv *env, jclass clazz, jstring wndClassName, jlong hInstance) +{ + ATOM res; + WNDCLASS wc; +#ifndef UNICODE + const char* _wndClassName = NULL; +#endif + + /* register class */ + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)wndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + /* This cast is legal because the HMODULE for a DLL is the same as + its HINSTANCE -- see MSDN docs for DllMain */ + wc.hInstance = (HINSTANCE) hInstance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); + wc.hbrBackground = GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = NULL; +#ifdef UNICODE + wc.lpszClassName = GetNullTerminatedStringChars(env, wndClassName); +#else + _wndClassName = (*env)->GetStringUTFChars(env, wndClassName, NULL); + wc.lpszClassName = strdup(_wndClassName); + (*env)->ReleaseStringUTFChars(env, wndClassName, _wndClassName); +#endif + res = RegisterClass(&wc); + + free((void *)wc.lpszClassName); + + return (jint)res; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: CleanupWindowResources + * Signature: (java/lang/String;J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CleanupWindowResources + (JNIEnv *env, jobject obj, jint wndClassAtom, jlong hInstance) +{ + UnregisterClass(MAKEINTATOM(wndClassAtom), (HINSTANCE) hInstance); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: CreateWindow + * Signature: (ILjava/lang/String;JJZIIII)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CreateWindow + (JNIEnv *env, jobject obj, jint wndClassAtom, jstring jWndName, jlong hInstance, jlong visualID, + jboolean bIsUndecorated, + jint jx, jint jy, jint defaultWidth, jint defaultHeight) +{ + const TCHAR* wndName = NULL; + DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + int x=(int)jx, y=(int)jy; + int width=(int)defaultWidth, height=(int)defaultHeight; + HWND window = NULL; + +#ifdef UNICODE + wndName = GetNullTerminatedStringChars(env, jWndName); +#else + wndName = (*env)->GetStringUTFChars(env, jWndName, NULL); +#endif + + x = CW_USEDEFAULT; + y = 0; + if (bIsUndecorated) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else { + windowStyle |= WS_OVERLAPPEDWINDOW; + } + + (void) visualID; // FIXME: use the visualID .. + + window = CreateWindow(MAKEINTATOM(wndClassAtom), wndName, windowStyle, + x, y, width, height, + NULL, NULL, + (HINSTANCE) hInstance, + NULL); + + if (window != NULL) { + WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData)); + wud->jinstance = (*env)->NewGlobalRef(env, obj); + wud->jenv = env; +#if defined(UNDER_CE) || _MSC_VER <= 1200 + SetWindowLong(window, GWL_USERDATA, (intptr_t) wud); +#else + SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud); +#endif + ShowWindow(window, SW_SHOWNORMAL); + } + +#ifdef UNICODE + free((void*) wndName); +#else + (*env)->ReleaseStringUTFChars(env, jWndName, wndName); +#endif + + return (jlong) (intptr_t) window; +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: DestroyWindow + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_DestroyWindow + (JNIEnv *env, jobject obj, jlong window) +{ + DestroyWindow((HWND) window); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: GetDC + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_GetDC + (JNIEnv *env, jobject obj, jlong window) +{ + return (jlong) GetDC((HWND) window); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: ReleaseDC + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_ReleaseDC + (JNIEnv *env, jobject obj, jlong window, jlong dc) +{ + ReleaseDC((HWND) window, (HDC) dc); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: MonitorFromWindow + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_MonitorFromWindow + (JNIEnv *env, jobject obj, jlong window) +{ + #if (_WIN32_WINNT >= 0x0500 || _WIN32_WINDOWS >= 0x0410 || WINVER >= 0x0500) && !defined(_WIN32_WCE) + return (jlong)MonitorFromWindow((HWND)window, MONITOR_DEFAULTTOPRIMARY); + #else + #warning NO MULTI MONITOR SUPPORT + return 0; + #endif +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setVisible0 + * Signature: (JZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setVisible0 + (JNIEnv *_env, jclass clazz, jlong window, jboolean visible) +{ + HWND hWnd = (HWND) (intptr_t) window; + if (visible) { + ShowWindow(hWnd, SW_SHOW); + } else { + ShowWindow(hWnd, SW_HIDE); + } +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: DispatchMessages + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_DispatchMessages + (JNIEnv *env, jclass clazz, jlong window, jint eventMask) +{ + int i = 0; + MSG msg; + BOOL gotOne; + WindowUserData * wud; + +#if defined(UNDER_CE) || _MSC_VER <= 1200 + wud = (WindowUserData *) GetWindowLong((HWND)window, GWL_USERDATA); +#else + wud = (WindowUserData *) GetWindowLongPtr((HWND)window, GWLP_USERDATA); +#endif + if(NULL==wud) { + fprintf(stderr, "INTERNAL ERROR in WindowsWindow::DispatchMessages window userdata NULL\n"); + exit(1); + } + + wud->jenv = env; + + if(eventMask<0) { + eventMask *= -1; + /* FIXME: re-select input mask + long xevent_mask_key = 0; + long xevent_mask_ptr = 0; + long xevent_mask_win = 0; + if( 0 != ( eventMask & EVENT_MOUSE ) ) { + xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; + } + if( 0 != ( eventMask & EVENT_KEY ) ) { + xevent_mask_key |= KeyPressMask|KeyReleaseMask; + } + if( 0 != ( eventMask & EVENT_WINDOW ) ) { + xevent_mask_win |= ExposureMask; + } + + XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); + */ + } + + // Periodically take a break + do { + gotOne = PeekMessage(&msg, (HWND) window, 0, 0, PM_REMOVE); + if (gotOne) { + ++i; + switch (msg.message) { + case WM_CLOSE: + case WM_DESTROY: + case WM_SIZE: + if( ! ( eventMask & EVENT_WINDOW ) ) { + continue; + } + break; + + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + if( ! ( eventMask & EVENT_KEY ) ) { + continue; + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEMOVE: + if( ! ( eventMask & EVENT_MOUSE ) ) { + continue; + } + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } while (gotOne && i < 100); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setSize0 + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setSize0 + (JNIEnv *env, jobject obj, jlong window, jint width, jint height) +{ + RECT r; + HWND w = (HWND) window; + GetWindowRect(w, &r); + MoveWindow(w, r.left, r.top, width, height, TRUE); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setPosition + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setPosition + (JNIEnv *env, jobject obj, jlong window, jint x, jint y) +{ + UINT flags = SWP_NOACTIVATE | SWP_NOZORDER; + HWND hwnd = (HWND)window; + RECT r; + + GetWindowRect(hwnd, &r); + SetWindowPos(hwnd, 0, x, y, (r.right-r.left), (r.bottom-r.top), flags); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setFullscreen + * Signature: (JIIIIZZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setFullscreen0 + (JNIEnv *env, jobject obj, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated, jboolean on) +{ + UINT flags; + HWND hwnd = (HWND)window; + HWND hWndInsertAfter; + DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + + if (bIsUndecorated || on) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else { + windowStyle |= WS_OVERLAPPEDWINDOW; + } + SetWindowLong(hwnd, GWL_STYLE, windowStyle); + + if(on==JNI_TRUE) { + flags = SWP_SHOWWINDOW; + hWndInsertAfter = HWND_TOPMOST; + } else { + flags = SWP_NOACTIVATE | SWP_NOZORDER; + hWndInsertAfter = 0; + } + + SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: setTitle + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setTitle + (JNIEnv *env, jclass clazz, jlong window, jstring title) +{ + HWND hwnd = (HWND)window; + if (title != NULL) { + jchar *titleString = GetNullTerminatedStringChars(env, title); + if (titleString != NULL) { + SetWindowTextW(hwnd, titleString); + free(titleString); + } + } +} + +/* + * Class: com_sun_javafx_newt_windows_WindowsWindow + * Method: requestFocus + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_requestFocus + (JNIEnv *env, jclass clazz, jlong window) +{ + HWND hwnd = (HWND)window; + + if (IsWindow(hwnd)) { + SetFocus(hwnd); + } +} diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c new file mode 100755 index 000000000..c3d446f09 --- /dev/null +++ b/src/newt/native/X11Window.c @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> + +#include "com_sun_javafx_newt_x11_X11Window.h" + +#include "EventListener.h" +#include "MouseEvent.h" +#include "KeyEvent.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(args...) fprintf(stderr, args) + + #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) + + static void _dumpVisualInfo(const char * msg, XVisualInfo *pVisualQuery) { + if(pVisualQuery!=NULL) { + fprintf(stderr, "%s: screen %d, visual: %p, visual-id: 0x%X, depth: %d, class %d, cmap sz: %d, bpp: 3x%d, rgb 0x%X 0x%X 0x%X\n", + msg, + pVisualQuery->screen, + pVisualQuery->visual, + (int)pVisualQuery->visualid, + pVisualQuery->depth, + pVisualQuery->class, + pVisualQuery->colormap_size, + pVisualQuery->bits_per_rgb, + (int)pVisualQuery->red_mask, + (int)pVisualQuery->green_mask, + (int)pVisualQuery->blue_mask + ); + } else { + fprintf(stderr, "%s: NULL XVisualInfo\n", msg); + } + } + +#else + + #define DBG_PRINT(args...) + + #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; +} + +/** + * Display + */ + +/* + * Class: com_sun_javafx_newt_x11_X11Display + * Method: CreateDisplay + * Signature: (Ljava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Display_CreateDisplay + (JNIEnv *env, jobject obj, jstring displayName) +{ + Display * dpy = NULL; + const char * _displayName = NULL; + if(displayName!=0) { + _displayName = (*env)->GetStringUTFChars(env, displayName, 0); + } + dpy = XOpenDisplay(_displayName); + if(_displayName!=0) { + (*env)->ReleaseStringChars(env, displayName, (const jchar *)_displayName); + } + if(dpy==NULL) { + fprintf(stderr, "couldn't open display connection..\n"); + } + return (jlong) (intptr_t) dpy; +} + +/** + * Screen + */ + +/* + * Class: com_sun_javafx_newt_x11_X11Screen + * Method: GetScreen + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Screen_GetScreen + (JNIEnv *env, jobject obj, jlong display, jint screen_index) +{ + Display * dpy = (Display *)(intptr_t)display; + Screen * scrn= NULL; + if(dpy==NULL) { + fprintf(stderr, "[GetScreen] invalid display connection..\n"); + return 0; + } + scrn = ScreenOfDisplay(dpy,screen_index); + if(scrn==NULL) { + scrn=DefaultScreenOfDisplay(dpy); + } + if(scrn==NULL) { + fprintf(stderr, "couldn't get screen ..\n"); + } + return (jlong) (intptr_t) scrn; +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_x11_X11Screen_getWidth0 + (JNIEnv *env, jobject obj, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) XDisplayWidth( dpy, scrn_idx); +} + +JNIEXPORT jint JNICALL Java_com_sun_javafx_newt_x11_X11Screen_getHeight0 + (JNIEnv *env, jobject obj, jlong display, jint scrn_idx) +{ + Display * dpy = (Display *) (intptr_t) display; + return (jint) XDisplayHeight( dpy, scrn_idx); +} + + +/** + * Window + */ + +static jmethodID sizeChangedID = NULL; +static jmethodID positionChangedID = NULL; +static jmethodID windowDestroyNotifyID = NULL; +static jmethodID windowDestroyedID = NULL; +static jmethodID windowCreatedID = NULL; +static jmethodID sendMouseEventID = NULL; +static jmethodID sendKeyEventID = NULL; + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_x11_X11Window_initIDs + (JNIEnv *env, jclass clazz) +{ + sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); + windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); + windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); + windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(JJ)V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + if (sizeChangedID == NULL || + positionChangedID == NULL || + windowDestroyNotifyID == NULL || + windowDestroyedID == NULL || + windowCreatedID == NULL || + sendMouseEventID == NULL || + sendKeyEventID == NULL) { + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: CreateWindow + * Signature: (JIJIIII)J + */ +JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_x11_X11Window_CreateWindow + (JNIEnv *env, jobject obj, jlong display, jint screen_index, + jlong visualID, + jint x, jint y, jint width, jint height) +{ + Display * dpy = (Display *)(intptr_t)display; + int scrn_idx = (int)screen_index; + Window windowParent = 0; + Window window = 0; + + XVisualInfo visualTemplate; + XVisualInfo *pVisualQuery = NULL; + Visual *visual = NULL; + int depth; + + XSetWindowAttributes xswa; + unsigned long attrMask; + int n; + + DBG_PRINT( "CreateWindow %x/%d %dx%d\n", x, y, width, height); + + if(dpy==NULL) { + fprintf(stderr, "[CreateWindow] invalid display connection..\n"); + return 0; + } + + if(visualID<0) { + fprintf(stderr, "[CreateWindow] invalid VisualID ..\n"); + return 0; + } + + XSync(dpy, False); + + Screen * scrn = ScreenOfDisplay(dpy, screen_index); + + // try given VisualID on screen + memset(&visualTemplate, 0, sizeof(XVisualInfo)); + visualTemplate.screen = scrn_idx; + visualTemplate.visualid = (VisualID)visualID; + pVisualQuery = XGetVisualInfo(dpy, VisualIDMask|VisualScreenMask, &visualTemplate,&n); + DUMP_VISUAL_INFO("Given VisualID,ScreenIdx", pVisualQuery); + if(pVisualQuery!=NULL) { + visual = pVisualQuery->visual; + depth = pVisualQuery->depth; + visualID = (jlong)pVisualQuery->visualid; + XFree(pVisualQuery); + pVisualQuery=NULL; + } + DBG_PRINT( "trying given (screen %d, visualID: %d) found: %p\n", scrn_idx, (int)visualID, visual); + + if (visual==NULL) + { + fprintf(stderr, "could not query Visual by given VisualID, bail out!\n"); + return 0; + } + + if(pVisualQuery!=NULL) { + XFree(pVisualQuery); + pVisualQuery=NULL; + } + + windowParent = XRootWindowOfScreen(scrn); + + attrMask = (CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect) ; + + memset(&xswa, 0, sizeof(xswa)); + xswa.override_redirect = False; // decorated + xswa.border_pixel = 0; + xswa.background_pixel = 0; + xswa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask; + xswa.colormap = XCreateColormap(dpy, + XRootWindow(dpy, scrn_idx), + visual, + AllocNone); + + window = XCreateWindow(dpy, + windowParent, + x, y, + width, height, + 0, // border width + depth, + InputOutput, + visual, + attrMask, + &xswa); + Atom wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + XSetWMProtocols(dpy, window, &wm_delete_window, 1); + XClearWindow(dpy, window); + XSync(dpy, False); + + (*env)->CallVoidMethod(env, obj, windowCreatedID, (jlong) window, (jlong)wm_delete_window); + + return (jlong) window; +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: CloseWindow + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_CloseWindow + (JNIEnv *env, jobject obj, jlong display, jlong window) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + XSync(dpy, False); + /** + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + */ + XSelectInput(dpy, w, 0); + XUnmapWindow(dpy, w); + XSync(dpy, False); + XDestroyWindow(dpy, w); + XSync(dpy, False); + (*env)->CallVoidMethod(env, obj, windowDestroyedID); +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setVisible0 + * Signature: (JJZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setVisible0 + (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean visible) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + DBG_PRINT( "setVisible0 vis %d\n", visible); + XSync(dpy, False); + if(visible==JNI_TRUE) { + XMapRaised(dpy, w); + XSync(dpy, False); + + // XSetInputFocus(dpy, w, RevertToParent, CurrentTime); + // XSync(dpy, False); + + } else { + /** + XUngrabPointer(dpy, CurrentTime); + XUngrabKeyboard(dpy, CurrentTime); + */ + XUnmapWindow(dpy, w); + XSync(dpy, False); + } +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: DispatchMessages + * Signature: (JJI)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_DispatchMessages + (JNIEnv *env, jobject obj, jlong display, jlong window, jint eventMask, jlong wmDeleteAtom) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + Atom wm_delete_window = (Atom)wmDeleteAtom; + + if(eventMask<0) { + long xevent_mask_key = 0; + long xevent_mask_ptr = 0; + long xevent_mask_win = 0; + eventMask *= -1; + if( 0 != ( eventMask & EVENT_MOUSE ) ) { + xevent_mask_ptr |= ButtonPressMask|ButtonReleaseMask|PointerMotionMask; + } + if( 0 != ( eventMask & EVENT_KEY ) ) { + xevent_mask_key |= KeyPressMask|KeyReleaseMask; + } + if( 0 != ( eventMask & EVENT_WINDOW ) ) { + xevent_mask_win |= ExposureMask | StructureNotifyMask | SubstructureNotifyMask | VisibilityNotify ; + } + + XSelectInput(dpy, w, xevent_mask_win|xevent_mask_key|xevent_mask_ptr); + + /** + if(0!=xevent_mask_ptr) { + XGrabPointer(dpy, w, True, xevent_mask_ptr, + GrabModeAsync, GrabModeAsync, w, None, CurrentTime); + } + if(0!=xevent_mask_key) { + XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } */ + + } + + // Periodically take a break + while( XPending(dpy)>0 ) { + XEvent evt; + KeySym keySym; + char keyChar; + char text[255]; + + XNextEvent(dpy, &evt); + + switch(evt.type) { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + if( ! ( eventMask & EVENT_MOUSE ) ) { + continue; + } + break; + case KeyPress: + case KeyRelease: + if( ! ( eventMask & EVENT_KEY ) ) { + continue; + } + break; + case FocusIn: + case FocusOut: + break; + case DestroyNotify: + case CreateNotify: + case VisibilityNotify: + case Expose: + case UnmapNotify: + if( ! ( eventMask & EVENT_WINDOW ) ) { + continue; + } + break; + } + + // FIXME: support resize and window re-positioning events + + switch(evt.type) { + case ButtonPress: + if(evt.xbutton.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + } + break; + case ButtonRelease: + if(evt.xbutton.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, + (jint) evt.xbutton.state, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); + } + break; + case MotionNotify: + if(evt.xmotion.window==w) { + (*env)->CallVoidMethod(env, obj, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, + (jint) evt.xmotion.state, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); + } + break; + case KeyPress: + if(evt.xkey.window==w) { + if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { + keyChar=text[0]; + } else { + keyChar=0; + } + (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_PRESSED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + } + break; + case KeyRelease: + if(evt.xkey.window==w) { + if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { + keyChar=text[0]; + } else { + keyChar=0; + } + (*env)->CallVoidMethod(env, obj, sendKeyEventID, (jint) EVENT_KEY_RELEASED, + (jint) evt.xkey.state, + X11KeySym2NewtVKey(keySym), (jchar) keyChar); + } + break; + case FocusIn: + case FocusOut: + if(evt.xfocus.window==w) { + } + break; + case DestroyNotify: + if(evt.xdestroywindow.window==w) { + DBG_PRINT( "event . DestroyNotify call 0x%X\n", evt.xdestroywindow.window); + (*env)->CallVoidMethod(env, obj, windowDestroyedID); + } + break; + case CreateNotify: + if(evt.xcreatewindow.window==w) { + DBG_PRINT( "event . DestroyNotify call 0x%X\n", evt.xcreatewindow.window); + (*env)->CallVoidMethod(env, obj, windowCreatedID); + } + break; + case VisibilityNotify: + if(evt.xvisibility.window==w) { + DBG_PRINT( "event . VisibilityNotify call 0x%X\n", evt.xvisibility.window); + } + break; + case Expose: + if(evt.xexpose.window==w) { + DBG_PRINT( "event . Expose call 0x%X\n", evt.xexpose.window); + /* FIXME: Might want to send a repaint event .. */ + } + break; + case UnmapNotify: + if(evt.xunmap.window==w) { + DBG_PRINT( "event . UnmapNotify call 0x%X\n", evt.xunmap.window); + } + break; + case ClientMessage: + if (evt.xclient.window==w && evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_window) { + DBG_PRINT( "event . ClientMessage call 0x%X type 0x%X !!!\n", evt.xclient.window, evt.xclient.message_type); + (*env)->CallVoidMethod(env, obj, windowDestroyNotifyID); + // Called by Window.java: CloseWindow(); + } + break; + + } + } +} + +#define MWM_FULLSCREEN 1 + +#ifdef MWM_FULLSCREEN + #define MWM_HINTS_DECORATIONS (1L << 1) + #define PROP_MWM_HINTS_ELEMENTS 5 +#endif + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setSize0 + * Signature: (JIJIIIIIZ)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setSize0 + (JNIEnv *env, jobject obj, jlong display, jint screen_index, jlong window, jint x, jint y, jint width, jint height, jint decorationToggle, jboolean isVisible) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); + Window parent = XRootWindowOfScreen(scrn); + + DBG_PRINT( "setSize0 %dx%d, dec %d, vis %d\n", width, height, decorationToggle, isVisible); + + XSync(dpy, False); + + if(0!=decorationToggle) { +#ifdef MWM_FULLSCREEN + unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { 0, 0, 0, 0, 0 }; // flags, functions, decorations, input_mode, status + Atom prop; + + mwmhints[0] = MWM_HINTS_DECORATIONS; + mwmhints[2] = (decorationToggle<0)?False:True; + prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", False ); + XChangeProperty( dpy, w, prop, prop, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS); +#else + XSetWindowAttributes xswa; + unsigned long attrMask=CWOverrideRedirect; + + if(decorationToggle<0) { + /* undecorated */ + xswa.override_redirect = True; + } else { + /* decorated */ + xswa.override_redirect = False; + } + XChangeWindowAttributes(dpy, w, attrMask, &xswa); + XReparentWindow( dpy, w, parent, x, y ); +#endif + } + XSync(dpy, False); + DBG_PRINT( "setSize0 . XConfigureWindow\n"); + XWindowChanges xwc; + xwc.width=width; + xwc.height=height; + XConfigureWindow(dpy, w, CWWidth|CWHeight, &xwc); + XReparentWindow( dpy, w, parent, x, y ); + + XSync(dpy, False); + + /** if(isVisible==JNI_TRUE) { + XSetInputFocus(dpy, w, RevertToNone, CurrentTime); + } */ + + DBG_PRINT( "setSize0 . sizeChangedID call\n"); + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_sun_javafx_newt_x11_X11Window + * Method: setPosition0 + * Signature: (JJII)V + */ +JNIEXPORT void JNICALL Java_com_sun_javafx_newt_x11_X11Window_setPosition0 + (JNIEnv *env, jobject obj, jlong display, jlong window, jint x, jint y) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + + DBG_PRINT( "setPos0 . XConfigureWindow\n"); + XWindowChanges xwc; + xwc.x=x; + xwc.y=y; + XConfigureWindow(dpy, w, CWX|CWY, &xwc); + XSync(dpy, False); + + // (*env)->CallVoidMethod(env, obj, positionChangedID, (jint) width, (jint) height); +} + |