diff --git a/sources/net.sf.j2s.core/dist/README.txt b/sources/net.sf.j2s.core/dist/README.txt index 80f9a1aeb..f167b9294 100644 --- a/sources/net.sf.j2s.core/dist/README.txt +++ b/sources/net.sf.j2s.core/dist/README.txt @@ -1,4 +1,6 @@ -SwingJS distribution README.txt +SwingJS distribution README.txt + +3/15/2018 Bob Hanson hansonr@stolaf.edu SwingJS has been successfully tested in Eclipse Neon and Oxygen on Mac and Windows platforms. (No reason to believe it would not also work for Linux; just haven't tried that recently.) @@ -7,30 +9,72 @@ INSTALLATION INSTRUCTIONS Eclipse Neon or higher is necessary. -1. net.sf.j2s.core_3.1.1.jar should be copied to the eclipse/dropins -directory **AS net.sf.j2s.core.jar dropping the version info** -because otherwise Eclipse will not recognize an update. +----------------------------------------------------------- +Installing the Java2Script transpiler as an Eclipse plug-in +----------------------------------------------------------- + +The Java2Script transpiler for SwingJS is in net.sf.j2s.core.jar. It parses the .java code and +creates .js files that match the standard .class files created by the Eclipse Java compiler. + +Note that both Java .class files (in bin/) and JavaScript .js files (in site/swingjs/j2s) are +created automatically anytime you do any building of your project. + + +1. Copy net.sf.j2s.core.jar from -We do not know why this is necessary, but it appears to be. If you leave -the version in the name, Eclipse will not be able to replace it with a -newer version later. From what we can tell. +https://github.com/BobHanson/java2script/blob/master/sources/net.sf.j2s.core/dist/dropins/net.sf.j2s.core.jar?raw=true -On Mac systems, this directory is +into your eclipse/dropins directory. + +Do not use net.sf.j2s.core_x.x.x.jar for this, as, if you do that, some versions of Eclipse will have to be +entirely reinstalled every time you change versions. We do not know why this is necessary, +but it appears to be. If you leave the version in the name, Eclipse will not be able to replace it with a +newer version later. From what we can tell. So just always use dist/dropins/net.sf.j2s.core.jar. + +On Mac systems, the Eclipse directory is /Applications/Eclipse.app/Contents/Eclipse/dropins -2. restart Eclipse and check for the presence of the plug-in at +2. Restart Eclipse and check for the presence of the plug-in at help...about Eclipse...installation details...Plug-ins...(wait several seconds for tabulation) search for "j2s" to find j2s.sourceforge.net Java2Script Core If that is not there, you don't have net.sf.j2s.core.jar in the proper directory. -3. Create an Eclipse Java project for your work, if you have not done so already. -If your source code is not all already in src/, navigate to the project...properties...Java Build Path...source -and add all the source directories you need. -4. Create in the Eclipse project the file: +---------------------------------- +Creating a new J2S/SwingJS project +---------------------------------- + +Create an Eclipse Java project for your work, if you have not done so already. +If your source code is not all already in src/, navigate to the project...properties... +Java Build Path...source and add all the source directories you need. + +Note that your project must not include any Jar file based dependencies. +All source code must be available. (Source code from decompiling .class files will work.) + + +--------------------------------------------------------------------- +Installing the SwingJS JavaScript version of the Java Virtual Machine +--------------------------------------------------------------------- + +All of the JavaScript produced will be in the project site/ directory. +You must prepopulate this site with all the JavaScript required by the +JavaScript version of the JVM. The most recent version of site/ is at + +https://github.com/BobHanson/java2script/blob/master/sources/net.sf.j2s.java.core/SwingJS-site.zip?raw=true + +Occasional additions to the java.* classes are made to the above-mentioned zip file. + +Simply download and unzip that file into your project, creating a top-level site/ directory. + + +------------------------------------------- +Enabling the Java2Script/SwingJS transpiler +------------------------------------------- + +1. Create in your Eclipse project the file: .j2s @@ -38,38 +82,74 @@ containing simply: j2s.compiler.status=enable -5. Modify the .project file to indicate the j2s transpiler is to be used, -changing the buildSpec buildCommand from +2. Edit the .project file to indicate that the j2s transpiler is to be used +rather than the standard Java compiler by changing the buildSpec buildCommand from -org.eclipse.jdt.core.javabuilder + org.eclipse.jdt.core.javabuilder to net.sf.j2s.core.java2scriptbuilder -6. All of the JavaScript produced will be in the project site/ directory. -You must prepopulate this site with all the JavaScript required by the -JavaScript version of the JVM. The most recent version of site/ is at -https://github.com/BobHanson/java2script/blob/master/sources/net.sf.j2s.java.core/SwingJS-site.zip?raw=true +-------------------- +Building the project +-------------------- -Occasional additions to the java.* classes are made to the above-mentioned zip file. +Build your project as you normally would. Java class files will be created as usual in the bin/ directory. +JavaScript equivalents of these files will be created in the site/swingjs/j2s directory. You might have to +do a project refresh to see these site files. + +Do take a look at the .js files created. You will notice that they are all the methods and fields of your +Java project *except* final static constants. SwingJS does not recreate those by name; it just uses them. +(The only thing this should affect is that java.lang.reflect.Field does not indicate these names.) + + +---------------------------------------------- +Testing the JavaScript version of your project +---------------------------------------------- + +The J2S transpiler will automatically set up for you in site/ a sample HTML page for any class +that subclasses JApplet or contains a public void main(String[] args) method. You will want to +associate those files with an external HTML browser. We recommend Firefox. -If you find you are missing a class, please contact me (Bob Hanson) at hansonr@stolaf.edu. -You can try adding these yourself by **temporarily** adding one or more of the -Java classes found at http://grepcode.com to the proper package. If you do that, be sure -to use the OpenJDK version. Most of the code in the SwingJS project started with Java 6-b14 or 6-b27. -Build your project, then delete these Java files, because you do not necessarily want your Java -code using that version, just JavaScript. +Since you will be running AJAX locally within these browsers, you may need to enable local +file reading in your browser. Instructions for doing that can be found at +http://wiki.jmol.org/index.php/Troubleshooting/Local_Files + + +------------------------ +Adding more Java classes +------------------------ + +If you find you are missing a Java class, please contact me (Bob Hanson) at hansonr@stolaf.edu. +You can try adding these yourself by **temporarily** adding one or more of the Java classes found +at http://grepcode.com to the proper package in your project. For example, java/awt. + +If you do that, be sure to use the OpenJDK version. Most of the code in the SwingJS project started with +Java 6-b14 or 6-b27. Build your project, then delete these Java files, because you do not necessarily +want your Java code using that version, just JavaScript. + + +---------------- +Working projects +---------------- A full site with many examples is at https://chemapps.stolaf.edu/swingjs/site +Falstad applets are in https://github.com/BobHanson/SwingJS-Examples +and appear at https://chemapps.stolaf.edu/swingjs/site + VARNA development is at https://github.com/BobHanson/VARNA working site is https://chemapps.stolaf.edu/swingjs/varna Physlets development is at https://github.com/BobHanson/Physlets-SwingJS working site is https://chemapps.stolaf.edu/swingjs/physlets +Phet applets have not been put on GitHub yet. + + + As of Feb. 17, 2018, we are actively converting a variety of functioning Java applets. The physlets Animator, Doppler, and Optics are working. diff --git a/sources/net.sf.j2s.java.core/SwingJS-site.zip b/sources/net.sf.j2s.java.core/SwingJS-site.zip index 2ae66095d..2d426b4a6 100644 Binary files a/sources/net.sf.j2s.java.core/SwingJS-site.zip and b/sources/net.sf.j2s.java.core/SwingJS-site.zip differ diff --git a/sources/net.sf.j2s.java.core/build_core_applet.xml b/sources/net.sf.j2s.java.core/build_core_applet.xml index 7cdb5b177..2ddebbad6 100644 --- a/sources/net.sf.j2s.java.core/build_core_applet.xml +++ b/sources/net.sf.j2s.java.core/build_core_applet.xml @@ -287,7 +287,7 @@ copying srcjs files into site - + diff --git a/sources/net.sf.j2s.java.core/src/java/awt/AWTKeyStroke.java b/sources/net.sf.j2s.java.core/src/java/awt/AWTKeyStroke.java index 3d388cb5a..f1cda6cb3 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/AWTKeyStroke.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/AWTKeyStroke.java @@ -5,7 +5,7 @@ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This code is free software; you can redistribute it and/or modify it + * This code is free software; you can redistribute it and/or modify itp * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided @@ -586,24 +586,15 @@ public static AWTKeyStroke getAWTKeyStroke(String s) { throw new IllegalArgumentException(errmsg); } - @SuppressWarnings("unused") private static VKCollection getVKCollection() { - if (vks == null) { - vks = new VKCollection(); - VKCollection vk = vks; - // TODO: THIS IS NOT GOING TO WORK ANYMORE -- WE DO NOT CREATE THE VK_ names - /** - * @j2sNative - * var c = Clazz.load("java.awt.event.KeyEvent"); - * for (var k in c) - * if (k.indexOf("VK_") == 0 && typeof c[k] == "number") - * vk.put(k, Integer.$valueOf(c[k])); - */ - {} - } - return vks; + return (vks == null ? (vks = new VKCollection()) : vks); } + public static void addKeyCode(String key, int keyCode) { + getVKCollection().put(key, Integer.valueOf(keyCode)); + } + + /** * Returns the integer constant for the KeyEvent.VK field named * key. This will throw an IllegalArgumentException @@ -611,29 +602,10 @@ private static VKCollection getVKCollection() { */ public static int getVKValue(String key) { VKCollection vkCollect = getVKCollection(); - Integer value = vkCollect.findCode(key); - if (value == null) { - int keyCode = 0; - final String errmsg = "String formatted incorrectly"; - - try { - /** - * @j2sNative - * - * keyCode = Clazz.load("java.awt.event.KeyEvent")[key]; - */ - { - keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class); - } - } catch (NoSuchFieldException nsfe) { - throw new IllegalArgumentException(errmsg); - } catch (IllegalAccessException iae) { - throw new IllegalArgumentException(errmsg); - } - value = Integer.valueOf(keyCode); - vkCollect.put(key, value); + vkCollect.put(key, Integer.valueOf(-1)); + throw new IllegalArgumentException("String formatted incorrectly"); } return value.intValue(); } @@ -862,6 +834,18 @@ class VKCollection { public VKCollection() { code2name = new HashMap(); name2code = new HashMap(); + + /** + * @j2sNative + * for (var k in C$) + * if (k.indexOf("VK_") == 0) { + * try { + * this.put$S$Integer(k, Integer.$valueOf(C$[k])); + * } catch (e) {} + * } + */ + + } public synchronized void put(String name, Integer code) { @@ -881,4 +865,616 @@ public synchronized String findName(Integer code) { // assert(code != null); return (String) code2name.get(code); } + + + + /* Virtual key codes copied from KeyEvent but not "final" */ + + static int VK_ENTER = 0x0A; // '\n' + static int VK_BACK_SPACE = 0x08; // '\b' + static int VK_TAB = 0x09; // '\t' + static int VK_CANCEL = 0x03; + static int VK_CLEAR = 0x0C; + static int VK_SHIFT = 0x10; + static int VK_CONTROL = 0x11; + static int VK_ALT = 0x12; + static int VK_PAUSE = 0x13; + static int VK_CAPS_LOCK = 0x14; + static int VK_ESCAPE = 0x1B; + static int VK_SPACE = 0x20; + static int VK_PAGE_UP = 0x21; + static int VK_PAGE_DOWN = 0x22; + static int VK_END = 0x23; + static int VK_HOME = 0x24; + + /** + * Constant for the non-numpad left arrow key. + * @see #VK_KP_LEFT + */ + static int VK_LEFT = 0x25; + + /** + * Constant for the non-numpad up arrow key. + * @see #VK_KP_UP + */ + static int VK_UP = 0x26; + + /** + * Constant for the non-numpad right arrow key. + * @see #VK_KP_RIGHT + */ + static int VK_RIGHT = 0x27; + + /** + * Constant for the non-numpad down arrow key. + * @see #VK_KP_DOWN + */ + static int VK_DOWN = 0x28; + + /** + * Constant for the comma key, "," + */ + static int VK_COMMA = 0x2C; + + /** + * Constant for the minus key, "-" + * @since 1.2 + */ + static int VK_MINUS = 0x2D; + + /** + * Constant for the period key, "." + */ + static int VK_PERIOD = 0x2E; + + /** + * Constant for the forward slash key, "/" + */ + static int VK_SLASH = 0x2F; + + /** VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ + static int VK_0 = 0x30; + static int VK_1 = 0x31; + static int VK_2 = 0x32; + static int VK_3 = 0x33; + static int VK_4 = 0x34; + static int VK_5 = 0x35; + static int VK_6 = 0x36; + static int VK_7 = 0x37; + static int VK_8 = 0x38; + static int VK_9 = 0x39; + + /** + * Constant for the semicolon key, ";" + */ + static int VK_SEMICOLON = 0x3B; + + /** + * Constant for the equals key, "=" + */ + static int VK_EQUALS = 0x3D; + + /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ + static int VK_A = 0x41; + static int VK_B = 0x42; + static int VK_C = 0x43; + static int VK_D = 0x44; + static int VK_E = 0x45; + static int VK_F = 0x46; + static int VK_G = 0x47; + static int VK_H = 0x48; + static int VK_I = 0x49; + static int VK_J = 0x4A; + static int VK_K = 0x4B; + static int VK_L = 0x4C; + static int VK_M = 0x4D; + static int VK_N = 0x4E; + static int VK_O = 0x4F; + static int VK_P = 0x50; + static int VK_Q = 0x51; + static int VK_R = 0x52; + static int VK_S = 0x53; + static int VK_T = 0x54; + static int VK_U = 0x55; + static int VK_V = 0x56; + static int VK_W = 0x57; + static int VK_X = 0x58; + static int VK_Y = 0x59; + static int VK_Z = 0x5A; + + /** + * Constant for the open bracket key, "[" + */ + static int VK_OPEN_BRACKET = 0x5B; + + /** + * Constant for the back slash key, "\" + */ + static int VK_BACK_SLASH = 0x5C; + + /** + * Constant for the close bracket key, "]" + */ + static int VK_CLOSE_BRACKET = 0x5D; + + static int VK_NUMPAD0 = 0x60; + static int VK_NUMPAD1 = 0x61; + static int VK_NUMPAD2 = 0x62; + static int VK_NUMPAD3 = 0x63; + static int VK_NUMPAD4 = 0x64; + static int VK_NUMPAD5 = 0x65; + static int VK_NUMPAD6 = 0x66; + static int VK_NUMPAD7 = 0x67; + static int VK_NUMPAD8 = 0x68; + static int VK_NUMPAD9 = 0x69; + static int VK_MULTIPLY = 0x6A; + static int VK_ADD = 0x6B; + + /** + * This constant is obsolete, and is included only for backwards + * compatibility. + * @see #VK_SEPARATOR + */ + static int VK_SEPARATER = 0x6C; + + /** + * Constant for the Numpad Separator key. + * @since 1.4 + */ + static int VK_SEPARATOR = VK_SEPARATER; + + static int VK_SUBTRACT = 0x6D; + static int VK_DECIMAL = 0x6E; + static int VK_DIVIDE = 0x6F; + static int VK_DELETE = 0x7F; /* ASCII DEL */ + static int VK_NUM_LOCK = 0x90; + static int VK_SCROLL_LOCK = 0x91; + + /** Constant for the F1 function key. */ + static int VK_F1 = 0x70; + + /** Constant for the F2 function key. */ + static int VK_F2 = 0x71; + + /** Constant for the F3 function key. */ + static int VK_F3 = 0x72; + + /** Constant for the F4 function key. */ + static int VK_F4 = 0x73; + + /** Constant for the F5 function key. */ + static int VK_F5 = 0x74; + + /** Constant for the F6 function key. */ + static int VK_F6 = 0x75; + + /** Constant for the F7 function key. */ + static int VK_F7 = 0x76; + + /** Constant for the F8 function key. */ + static int VK_F8 = 0x77; + + /** Constant for the F9 function key. */ + static int VK_F9 = 0x78; + + /** Constant for the F10 function key. */ + static int VK_F10 = 0x79; + + /** Constant for the F11 function key. */ + static int VK_F11 = 0x7A; + + /** Constant for the F12 function key. */ + static 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. */ + static int VK_F13 = 0xF000; + + /** + * Constant for the F14 function key. + * @since 1.2 + */ + static int VK_F14 = 0xF001; + + /** + * Constant for the F15 function key. + * @since 1.2 + */ + static int VK_F15 = 0xF002; + + /** + * Constant for the F16 function key. + * @since 1.2 + */ + static int VK_F16 = 0xF003; + + /** + * Constant for the F17 function key. + * @since 1.2 + */ + static int VK_F17 = 0xF004; + + /** + * Constant for the F18 function key. + * @since 1.2 + */ + static int VK_F18 = 0xF005; + + /** + * Constant for the F19 function key. + * @since 1.2 + */ + static int VK_F19 = 0xF006; + + /** + * Constant for the F20 function key. + * @since 1.2 + */ + static int VK_F20 = 0xF007; + + /** + * Constant for the F21 function key. + * @since 1.2 + */ + static int VK_F21 = 0xF008; + + /** + * Constant for the F22 function key. + * @since 1.2 + */ + static int VK_F22 = 0xF009; + + /** + * Constant for the F23 function key. + * @since 1.2 + */ + static int VK_F23 = 0xF00A; + + /** + * Constant for the F24 function key. + * @since 1.2 + */ + static int VK_F24 = 0xF00B; + + static int VK_PRINTSCREEN = 0x9A; + static int VK_INSERT = 0x9B; + static int VK_HELP = 0x9C; + static int VK_META = 0x9D; + + static int VK_BACK_QUOTE = 0xC0; + static int VK_QUOTE = 0xDE; + + /** + * Constant for the numeric keypad up arrow key. + * @see #VK_UP + * @since 1.2 + */ + static int VK_KP_UP = 0xE0; + + /** + * Constant for the numeric keypad down arrow key. + * @see #VK_DOWN + * @since 1.2 + */ + static int VK_KP_DOWN = 0xE1; + + /** + * Constant for the numeric keypad left arrow key. + * @see #VK_LEFT + * @since 1.2 + */ + static int VK_KP_LEFT = 0xE2; + + /** + * Constant for the numeric keypad right arrow key. + * @see #VK_RIGHT + * @since 1.2 + */ + static int VK_KP_RIGHT = 0xE3; + + /* For European keyboards */ + /** @since 1.2 */ + static int VK_DEAD_GRAVE = 0x80; + /** @since 1.2 */ + static int VK_DEAD_ACUTE = 0x81; + /** @since 1.2 */ + static int VK_DEAD_CIRCUMFLEX = 0x82; + /** @since 1.2 */ + static int VK_DEAD_TILDE = 0x83; + /** @since 1.2 */ + static int VK_DEAD_MACRON = 0x84; + /** @since 1.2 */ + static int VK_DEAD_BREVE = 0x85; + /** @since 1.2 */ + static int VK_DEAD_ABOVEDOT = 0x86; + /** @since 1.2 */ + static int VK_DEAD_DIAERESIS = 0x87; + /** @since 1.2 */ + static int VK_DEAD_ABOVERING = 0x88; + /** @since 1.2 */ + static int VK_DEAD_DOUBLEACUTE = 0x89; + /** @since 1.2 */ + static int VK_DEAD_CARON = 0x8a; + /** @since 1.2 */ + static int VK_DEAD_CEDILLA = 0x8b; + /** @since 1.2 */ + static int VK_DEAD_OGONEK = 0x8c; + /** @since 1.2 */ + static int VK_DEAD_IOTA = 0x8d; + /** @since 1.2 */ + static int VK_DEAD_VOICED_SOUND = 0x8e; + /** @since 1.2 */ + static int VK_DEAD_SEMIVOICED_SOUND = 0x8f; + + /** @since 1.2 */ + static int VK_AMPERSAND = 0x96; + /** @since 1.2 */ + static int VK_ASTERISK = 0x97; + /** @since 1.2 */ + static int VK_QUOTEDBL = 0x98; + /** @since 1.2 */ + static int VK_LESS = 0x99; + + /** @since 1.2 */ + static int VK_GREATER = 0xa0; + /** @since 1.2 */ + static int VK_BRACELEFT = 0xa1; + /** @since 1.2 */ + static int VK_BRACERIGHT = 0xa2; + + /** + * Constant for the "@" key. + * @since 1.2 + */ + static int VK_AT = 0x0200; + + /** + * Constant for the ":" key. + * @since 1.2 + */ + static int VK_COLON = 0x0201; + + /** + * Constant for the "^" key. + * @since 1.2 + */ + static int VK_CIRCUMFLEX = 0x0202; + + /** + * Constant for the "$" key. + * @since 1.2 + */ + static int VK_DOLLAR = 0x0203; + + /** + * Constant for the Euro currency sign key. + * @since 1.2 + */ + static int VK_EURO_SIGN = 0x0204; + + /** + * Constant for the "!" key. + * @since 1.2 + */ + static int VK_EXCLAMATION_MARK = 0x0205; + + /** + * Constant for the inverted exclamation mark key. + * @since 1.2 + */ + static int VK_INVERTED_EXCLAMATION_MARK = 0x0206; + + /** + * Constant for the "(" key. + * @since 1.2 + */ + static int VK_LEFT_PARENTHESIS = 0x0207; + + /** + * Constant for the "#" key. + * @since 1.2 + */ + static int VK_NUMBER_SIGN = 0x0208; + + /** + * Constant for the "+" key. + * @since 1.2 + */ + static int VK_PLUS = 0x0209; + + /** + * Constant for the ")" key. + * @since 1.2 + */ + static int VK_RIGHT_PARENTHESIS = 0x020A; + + /** + * Constant for the "_" key. + * @since 1.2 + */ + static 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 + */ + static int VK_WINDOWS = 0x020C; + + /** + * Constant for the Microsoft Windows Context Menu key. + * @since 1.5 + */ + static int VK_CONTEXT_MENU = 0x020D; + + /* for input method support on Asian Keyboards */ + + /* not clear what this means - listed in Microsoft Windows API */ + static int VK_FINAL = 0x0018; + + /** Constant for the Convert function key. */ + /* Japanese PC 106 keyboard, Japanese Solaris keyboard: henkan */ + static int VK_CONVERT = 0x001C; + + /** Constant for the Don't Convert function key. */ + /* Japanese PC 106 keyboard: muhenkan */ + static int VK_NONCONVERT = 0x001D; + + /** Constant for the Accept or Commit function key. */ + /* Japanese Solaris keyboard: kakutei */ + static int VK_ACCEPT = 0x001E; + + /* not clear what this means - listed in Microsoft Windows API */ + static int VK_MODECHANGE = 0x001F; + + /* replaced by VK_KANA_LOCK for Microsoft Windows and Solaris; + might still be used on other platforms */ + static int VK_KANA = 0x0015; + + /* replaced by VK_INPUT_METHOD_ON_OFF for Microsoft Windows and Solaris; + might still be used for other platforms */ + static int VK_KANJI = 0x0019; + + /** + * Constant for the Alphanumeric function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: eisuu */ + static int VK_ALPHANUMERIC = 0x00F0; + + /** + * Constant for the Katakana function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: katakana */ + static int VK_KATAKANA = 0x00F1; + + /** + * Constant for the Hiragana function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: hiragana */ + static int VK_HIRAGANA = 0x00F2; + + /** + * Constant for the Full-Width Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: zenkaku */ + static int VK_FULL_WIDTH = 0x00F3; + + /** + * Constant for the Half-Width Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: hankaku */ + static int VK_HALF_WIDTH = 0x00F4; + + /** + * Constant for the Roman Characters function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard: roumaji */ + static int VK_ROMAN_CHARACTERS = 0x00F5; + + /** + * Constant for the All Candidates function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_CONVERT + ALT: zenkouho */ + static int VK_ALL_CANDIDATES = 0x0100; + + /** + * Constant for the Previous Candidate function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_CONVERT + SHIFT: maekouho */ + static int VK_PREVIOUS_CANDIDATE = 0x0101; + + /** + * Constant for the Code Input function key. + * @since 1.2 + */ + /* Japanese PC 106 keyboard - VK_ALPHANUMERIC + ALT: kanji bangou */ + static 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 */ + static 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 */ + static 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 */ + static 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 */ + static 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 */ + static int VK_INPUT_METHOD_ON_OFF = 0x0107; + + /* for Sun keyboards */ + /** @since 1.2 */ + static int VK_CUT = 0xFFD1; + /** @since 1.2 */ + static int VK_COPY = 0xFFCD; + /** @since 1.2 */ + static int VK_PASTE = 0xFFCF; + /** @since 1.2 */ + static int VK_UNDO = 0xFFCB; + /** @since 1.2 */ + static int VK_AGAIN = 0xFFC9; + /** @since 1.2 */ + static int VK_FIND = 0xFFD0; + /** @since 1.2 */ + static int VK_PROPS = 0xFFCA; + /** @since 1.2 */ + static int VK_STOP = 0xFFC8; + + /** + * Constant for the Compose function key. + * @since 1.2 + */ + static int VK_COMPOSE = 0xFF20; + + /** + * Constant for the AltGraph function key. + * @since 1.2 + */ + static int VK_ALT_GRAPH = 0xFF7E; + + /** + * Constant for the Begin key. + * @since 1.5 + */ + static int VK_BEGIN = 0xFF58; + } diff --git a/sources/net.sf.j2s.java.core/src/swingjs/JSKeyEvent.java b/sources/net.sf.j2s.java.core/src/swingjs/JSKeyEvent.java new file mode 100644 index 000000000..724ed1c2a --- /dev/null +++ b/sources/net.sf.j2s.java.core/src/swingjs/JSKeyEvent.java @@ -0,0 +1,161 @@ +package swingjs; + +import java.awt.AWTKeyStroke; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import javax.swing.JComponent; + +/** + * Handle the conversion between JavaScript and Java key events. + * + * used by plaf/JSListUI and plaf/JSTextUI; should be implemented for all + * components? + * + * @author Bob Hanson + * @author Trai Nguyen + * + */ +@SuppressWarnings({"serial", "unused"}) +public class JSKeyEvent extends KeyEvent { + + public static JSKeyEvent newJSKeyEvent(JComponent source, Object jQueryEvent, boolean isList) { + + // JavaScript: keydown keypress keyup + // Java: KEY_PRESSED KEY_TYPED* KEY_RELEASED + // Java code/char 0/char code/char + // + // *KEY_TYPED only when keyChar not CHAR_UNDEFINED (0xFFFF) + + String evType = null, jskey = null; + int jskeyCode = 0, jskeyLocation = 0; + Object ev = jQueryEvent; + + /** + * @j2sNative + * + * evType = ev.type; jskey = ev.key; + * jskeyCode = ev.keyCode || ev.which; + * jskeyLocation = ev.originalEvent.location || 0; + * if (isList && evType == "keypress") + * ev.originalEvent.preventDefault(); + */ + + int id = (evType == "keydown" ? KEY_PRESSED + : evType == "keypress" ? KEY_TYPED + : evType == "keyup" ? KEY_RELEASED + : 0); + int keyCode = getJavaKeyCode(jskeyCode, jskey); + char keyChar = getJavaKeyChar(keyCode, jskey); + return (id == 0 || keyChar == CHAR_UNDEFINED && id == KEY_TYPED ? null + : new JSKeyEvent(source, jQueryEvent, id, + (id == KEY_TYPED ? JSKeyEvent.VK_UNDEFINED : keyCode), + keyChar, + (id == KEY_TYPED ? KEY_LOCATION_UNKNOWN : jskeyLocation + 1)) + ); + } + + private JSKeyEvent(JComponent source, Object ev, int id, int keyCode, char keyChar, int location) { + super(source, id, System.currentTimeMillis(), 0, keyCode, keyChar, location); + boolean shift = false, ctrl = false, meta = false, alt = false, altGraph = false; + /** + * @j2sNative + * + * shift = ev.shiftKey; + * ctrl = ev.ctrlKey; + * alt = ev.altKey; + * meta = ev.metaKey; + * altGraph = ev.altGraphKey; + */ + modifiers = JSKeyEvent.getModifiers(shift, ctrl, alt, meta, altGraph); + } + + private static int getJavaKeyCode(int jskeyCode, String jskey) { + // see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values + if (jskeyCode <= 40) { + // enter is special + if (jskeyCode == 13) + return VK_ENTER; + // other 0-40 is same + return jskeyCode; + } + if (jskey.length() == 1) { + // same if 1-character, except numeric keypad 0-9 + return (jskeyCode >= 96 && jskeyCode <= 105 ? jskeyCode : 0 + jskey.toUpperCase().charAt(0)); + } + switch (jskeyCode) { + case 91: // META + return VK_META; + case 93: // CONTEXT_MENU + return VK_CONTEXT_MENU; + case 144: // NUM_LOCK + case 145: // SCROLL_LOCK + return jskeyCode; + case 244: // Kanji + return VK_KANJI; + } + String keyName = "VK_" + jskey.toUpperCase(); + try { + // get the Java code from AWTKeyStroke by name, if possible + return AWTKeyStroke.getVKValue(keyName); + } catch (Exception e) { + // or add this jskeycode to the Java list and note that on System.out + System.out.println("JSKeyEvent adding key/keyCode " + keyName + " " + jskeyCode); + AWTKeyStroke.addKeyCode(keyName, jskeyCode); + } + return jskeyCode; + } + + private static char getJavaKeyChar(int jsKeyCode, String jskey) { + if (jskey.length() == 1) + return jskey.charAt(0); + // valid Java characters that are named in JavaScript + switch (jsKeyCode) { + case 13: + jsKeyCode = VK_ENTER; + // fall through + case VK_ENTER: + case VK_BACK_SPACE: + case VK_TAB: + case VK_DELETE: + case VK_ESCAPE: + return (char) jsKeyCode; + default: + return '\uFFFF'; + } + } + + private static boolean hasKeyChar(int javaKeyCode, String jskey) { + switch (javaKeyCode) { + case VK_ENTER: + case VK_BACK_SPACE: + case VK_TAB: + case VK_DELETE: + case VK_ESCAPE: + return true; + default: + // otherwise only single-char jskeys have characters in Java + return (jskey.length() == 1); + } + + } + + private static int getModifiers(boolean shift, boolean ctrl, boolean alt, boolean meta, boolean altGraph) { + int modifiers = 0; + if (shift) + modifiers |= InputEvent.SHIFT_MASK + InputEvent.SHIFT_DOWN_MASK; + if (ctrl) + modifiers |= InputEvent.CTRL_MASK + InputEvent.CTRL_DOWN_MASK; + if (alt) + modifiers |= InputEvent.ALT_MASK + InputEvent.ALT_DOWN_MASK; + if (meta) + modifiers |= InputEvent.META_MASK + InputEvent.META_DOWN_MASK; + if (altGraph) + modifiers |= InputEvent.ALT_GRAPH_MASK + InputEvent.ALT_GRAPH_DOWN_MASK; + + + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSKeyEvent.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSKeyEvent.java deleted file mode 100644 index 4f542cdf7..000000000 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSKeyEvent.java +++ /dev/null @@ -1,105 +0,0 @@ -package swingjs.plaf; - -import java.awt.AWTKeyStroke; -import java.awt.event.KeyEvent; - -import javax.swing.JComponent; - -@SuppressWarnings({"serial", "unused"}) -public class JSKeyEvent extends KeyEvent { - - -//Alphanumeric keys -// VK_0, VK_1, ..., VK_9, VK_A, VK_B, ..., VK_Z -//Java: pressed/typed/released (typed has charCode 0; pressed has UCASE keyCode but true-case keyChar -//JavaScript: down/pressed/up - -//Control keys -// VK_ENTER, VK_BACKSPACE, VK_TAB, VK_ESCAPE -//Java: pressed/typed/released (typed has charCode 0; pressed has UCASE keyCode but true-case keyChar -//JavaScript: down/pressed/up - -//Function keys -// VK_F1, VK_F2, VK_F3, VK_F4 VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, -// VK_SCROLL_LOCK, VK_PRINTSCREEN, VK_PAUSE, -// VK_DELETE, VK_INSERT, -// VK_PAGE_UP, VK_PAGE_DOWN, VK_HOME, VK_END -//Java: pressed/released only, with keyChar 0xFFFF -// DEL: adds 0 127 typed -// INS: code is 155 -//JavaScript: down/pressed/up; only up for printScreen -// DEL: code is 46 -// INS: code is 45 - -//Arrow keys -// VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN -//Java: pressed/released 38/0xFFFF -//JavaScript: down/pressed/up 38/"ArrowUp" - - Object jqEvent; - - public JSKeyEvent(JComponent source, Object jQueryEvent) { - super(); - String evType = null; - int keyCode = 0; - int which = 0; - int modifiers = 0; - int id = 0; - long when = System.currentTimeMillis(); - char keyChar = 0; - int keyLocation = KeyEvent.KEY_LOCATION_UNKNOWN; - String key = ""; - Object ev = jQueryEvent; - /** - * @j2sNative - * - * key = ev.key; - * evType = ev.type; - * keyCode = ev.keyCode || ev.which; - * if (keyCode == 13) keyCode = 10; - * if (evType == "keypress") - * ev.originalEvent.preventDefault(); - * - * - * if (ev.shiftKey) - modifiers |= (1<<0)|(1<<6); //InputEvent.SHIFT_MASK + InputEvent.SHIFT_DOWN_MASK; - if (ev.ctrlKey) - modifiers |= (1<<1)|(1<<7); //InputEvent.CTRL_MASK + InputEvent.CTRL_DOWN_MASK; - if (ev.metaKey) - modifiers |= (1<<2)|(1<<8); //InputEvent.META_MASK + InputEvent.META_DOWN_MASK; - if (ev.altKey) - modifiers |= (1<<3)|(1<<9); //InputEvent.ALT_MASK + InputEvent.ALT_DOWN_MASK; - if (ev.altGraphKey) - modifiers |= (1<<5)|(1<<13); //InputEvent.ALT_GRAPH_MASK + InputEvent.ALT_GRAPH_DOWN_MASK; - * - * if (keyCode == 8 && evType == "keypress") ev.originalEvent.preventDefault(); - */ - {} - - // JavaScript: keydown keypress keyup - // Java: KEY_PRESSED KEY_TYPED KEY_RELEASED - - id = (evType == "keydown" ? KeyEvent.KEY_PRESSED : evType == "keypress" ? KeyEvent.KEY_TYPED : evType == "keyup" ? KeyEvent.KEY_RELEASED : 0); - this.source = source; - this.id = id; - this.when = when; - this.modifiers = modifiers; - this.keyCode = keyCode; - int ch; - int test; - try { - // only safe thing to do is get Java's keyCode from itself - // for example, "Delete" is 46 instead of 127 - this.keyCode = (key.length() == 1 ? 0 - + (id == 400 ? '\0' : key.toUpperCase().charAt(0)) - : keyCode == 10 || keyCode == 8 || keyCode == 9 ? 0 : - (ch = AWTKeyStroke.getVKValue ("VK_" + key.toUpperCase())) == 0 ? keyCode : ch); - } catch (Exception e) { - // ignore - } - this.keyChar = (key.length() == 1 ? key.charAt(0) : keyCode == 10 ? '\n' : keyCode == 8 ? '\b' : keyCode == 9 ? '\t' : '\0'); - this.keyLocation = keyLocation; - this.jqEvent = ev; - } - -} diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java index 3dfda6359..663f048f6 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSListUI.java @@ -70,6 +70,7 @@ import sun.swing.DefaultLookup; import sun.swing.SwingUtilities2; import sun.swing.UIAction; +import swingjs.JSKeyEvent; import swingjs.JSUtil; //import java.awt.datatransfer.Transferable; //import javax.swing.BorderFactory; @@ -137,7 +138,9 @@ protected DOMNode updateDOMNode() { public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { switch (eventType) { case KeyEvent.KEY_PRESSED: - jc.dispatchEvent(new JSKeyEvent(jc, jQueryEvent)); + JSKeyEvent keyEvent = JSKeyEvent.newJSKeyEvent(jc, jQueryEvent, true); + if (keyEvent != null) + jc.dispatchEvent(keyEvent); break; } return true; diff --git a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextUI.java b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextUI.java index 80761dff4..1cc9cd138 100644 --- a/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextUI.java +++ b/sources/net.sf.j2s.java.core/src/swingjs/plaf/JSTextUI.java @@ -34,7 +34,6 @@ import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; import javax.swing.AbstractAction; import javax.swing.Action; @@ -53,8 +52,9 @@ import javax.swing.text.EditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.TextAction; + +import swingjs.JSKeyEvent; import swingjs.JSToolkit; -import swingjs.JSUtil; import swingjs.api.js.DOMNode; /** @@ -224,57 +224,9 @@ public boolean handleJSEvent(Object target, int eventType, Object jQueryEvent) { switch (eventType) { case KeyEvent.KEY_PRESSED: // note that events are bundled here into one eventType - int keyCode = 0; - int modifiers = JSUtil.J2S._getKeyModifiers(jQueryEvent); - char keyChar = '\0'; - String type = null; - /** - * @j2sNative - * - * keyCode = jQueryEvent.keyCode; - * keyChar = jQueryEvent.key; - * type = jQueryEvent.type; - * - */ - switch (type) { - case "keydown": - eventType = KeyEvent.KEY_PRESSED; - break; - case "keypress": - // igonred by Java for - - -// Control keys -// VK_ENTER, VK_BACKSPACE, VK_TAB, VK_ESCAPE -// Function keys -// VK_F1, VK_F2, VK_F3, VK_F4 VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, -// VK_SCROLL_LOCK, VK_PRINTSCREEN, VK_PAUSE, -// VK_DELETE, VK_INSERT, -// VK_PAGE_UP, VK_PAGE_DOWN, VK_HOME, VK_END -// Java: pressed/released only, with keyChar 0xFFFF -// DEL: adds 0 127 typed -// INS: code is 155 -// JavaScript: down/pressed/up; but only up for printScreen -// PRINTSCREEN code is 44 -// INS: code is 45 -// DEL: code is 46 -// -// Arrow keys -// VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN -// Java: pressed/released 38/0xFFFF -// -// - - // TODO: generate this for BACKSPACE and what other keys? - eventType = KeyEvent.KEY_TYPED; - keyChar = (char) keyCode; - keyCode = KeyEvent.VK_UNDEFINED; - break; - case "keyup": - eventType = KeyEvent.KEY_RELEASED; - break; - } - KeyEvent keyEvent = new KeyEvent(jc, eventType, System.currentTimeMillis(), modifiers, keyCode, keyChar); + JSKeyEvent keyEvent = JSKeyEvent.newJSKeyEvent(jc, jQueryEvent, false); + if (keyEvent == null) + return true; jc.dispatchEvent(keyEvent); if (keyEvent.isConsumed()) { /** diff --git a/sources/net.sf.j2s.java.core/srcjs/README.txt b/sources/net.sf.j2s.java.core/srcjs/README.txt index fd5afba49..9618ab028 100644 --- a/sources/net.sf.j2s.java.core/srcjs/README.txt +++ b/sources/net.sf.j2s.java.core/srcjs/README.txt @@ -1,9 +1,19 @@ -This directory contains: +This directory: +- preserves files that need to be present in site/ as swingjs2.js +- stores the files that build_core_applet.xml needs to create swingjs/j2s/core/ and swingjs/swingjs2.js files -js/*.js a set of files needed for all SwingJS pagees + +It contains: + + +js/*.js a set of files needed for all SwingJS pages js/make.bat a script that concatenates the *.js files in the right order to make swingjs2.js + It is here as a convenience only; when in site/js, a developer can run this script + to test changes. It is not used by build_core_applet.xml, which uses ANT concat instead. + js/core/ a folder used by build_core_applet.xml to create Google closure-compiled swingjs/j2s/core files. - \ No newline at end of file + + diff --git a/sources/net.sf.j2s.java.core/srcjs/js/README.txt b/sources/net.sf.j2s.java.core/srcjs/js/README.txt deleted file mode 100644 index fd5afba49..000000000 --- a/sources/net.sf.j2s.java.core/srcjs/js/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -This directory contains: - - -js/*.js a set of files needed for all SwingJS pagees - -js/make.bat a script that concatenates the *.js files in the right order to make swingjs2.js - -js/core/ a folder used by build_core_applet.xml to create Google closure-compiled swingjs/j2s/core files. - \ No newline at end of file diff --git a/sources/net.sf.j2s.java.core/srcjs/js/j2sApplet.js b/sources/net.sf.j2s.java.core/srcjs/js/j2sApplet.js index a25e20a05..3fdeb9e04 100644 --- a/sources/net.sf.j2s.java.core/srcjs/js/j2sApplet.js +++ b/sources/net.sf.j2s.java.core/srcjs/js/j2sApplet.js @@ -1,5 +1,6 @@ // j2sCore.js (based on JmolCore.js) +// BH 3/16/2018 5:25:09 AM fixes for dragging on phones // BH 2/20/2018 12:08:08 AM adds J2S._getKeyModifiers // BH 1/8/2018 10:27:46 PM SwingJS2 // BH 12/22/2017 1:18:42 PM adds j2sargs for setting arguments @@ -1287,8 +1288,11 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection J2S.$bind(who, 'mousedown touchstart', function(ev) { + // System.out.println(["j2sApplet DOWN",ev.type,doIgnore(ev),ev.target.id,ev.target.getAttribute("role"),ev.target["data-ui"]]); + lastDragx = lastDragy = 99999; + if (doIgnore(ev)) return true; @@ -1472,6 +1476,9 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection var getMouseModifiers = function(ev) { var modifiers = 0; switch (ev.button) { + default: + ev.button = 0; + // fall through case 0: modifiers = (1<<4)|(1<<10);//InputEvent.BUTTON1 + InputEvent.BUTTON1_DOWN_MASK; break; @@ -1561,6 +1568,9 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection return true; } + var lastDragx = 99999; + var lastDragy = 99999; + J2S._drag = function(who, ev) { ev.stopPropagation(); @@ -1572,7 +1582,12 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection var xym = J2S._jsGetXY(who, ev); if(!xym) return false; - if (!who.isDragging) + if (lastDragx == xym[0] && lastDragy == xym[1]) + return false; + lastDragx = xym[0]; + lastDragy = xym[1]; + + if (!who.isDragging) xym[2] = 0; var ui = ev.target["data-ui"]; diff --git a/sources/net.sf.j2s.java.core/srcjs/swingjs2.js b/sources/net.sf.j2s.java.core/srcjs/swingjs2.js index c6f9fd589..dba1744a7 100644 --- a/sources/net.sf.j2s.java.core/srcjs/swingjs2.js +++ b/sources/net.sf.j2s.java.core/srcjs/swingjs2.js @@ -10654,6 +10654,7 @@ return jQuery; })(jQuery,document,"click mousemove mouseup touchmove touchend", "outjsmol"); // j2sCore.js (based on JmolCore.js) +// BH 3/16/2018 5:25:09 AM fixes for dragging on phones // BH 2/20/2018 12:08:08 AM adds J2S._getKeyModifiers // BH 1/8/2018 10:27:46 PM SwingJS2 // BH 12/22/2017 1:18:42 PM adds j2sargs for setting arguments @@ -11941,8 +11942,11 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection J2S.$bind(who, 'mousedown touchstart', function(ev) { + // System.out.println(["j2sApplet DOWN",ev.type,doIgnore(ev),ev.target.id,ev.target.getAttribute("role"),ev.target["data-ui"]]); + lastDragx = lastDragy = 99999; + if (doIgnore(ev)) return true; @@ -12126,6 +12130,9 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection var getMouseModifiers = function(ev) { var modifiers = 0; switch (ev.button) { + default: + ev.button = 0; + // fall through case 0: modifiers = (1<<4)|(1<<10);//InputEvent.BUTTON1 + InputEvent.BUTTON1_DOWN_MASK; break; @@ -12215,6 +12222,9 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection return true; } + var lastDragx = 99999; + var lastDragy = 99999; + J2S._drag = function(who, ev) { ev.stopPropagation(); @@ -12226,7 +12236,12 @@ J2S._getDefaultLanguage = function(isAll) { return (isAll ? J2S.featureDetection var xym = J2S._jsGetXY(who, ev); if(!xym) return false; - if (!who.isDragging) + if (lastDragx == xym[0] && lastDragy == xym[1]) + return false; + lastDragx = xym[0]; + lastDragy = xym[1]; + + if (!who.isDragging) xym[2] = 0; var ui = ev.target["data-ui"];