From b415db23e112db33bbb714b1c031d99e5ba92d10 Mon Sep 17 00:00:00 2001 From: benfry Date: Tue, 13 Nov 2012 17:26:06 +0000 Subject: [PATCH] rewriting event queue setup, changing default imports, general havoc --- android/todo.txt | 4 +- .../processing/mode/android/AndroidBuild.java | 3 +- .../mode/android/AndroidPreprocessor.java | 12 +- app/src/processing/mode/java/JavaBuild.java | 1 + .../mode/java/preproc/PdePreprocessor.java | 3 +- build/shared/lib/preferences.txt | 9 +- core/src/processing/core/PApplet.java | 293 +++++++++++++----- core/src/processing/event/Event.java | 36 ++- core/src/processing/event/KeyEvent.java | 1 + core/src/processing/event/MouseEvent.java | 1 + core/src/processing/event/TouchEvent.java | 1 + core/todo.txt | 6 +- 12 files changed, 266 insertions(+), 104 deletions(-) diff --git a/android/todo.txt b/android/todo.txt index e926824a9..c33b2e898 100644 --- a/android/todo.txt +++ b/android/todo.txt @@ -1,5 +1,7 @@ 0215 android - +X removing default imports for +X android.view.MotionEvent, android.view.KeyEvent,android.graphics.Bitmap +X due to conflicts w/ the new p5 event system _ implement Android version of command line tools _ http://code.google.com/p/processing/issues/detail?id=1323 diff --git a/app/src/processing/mode/android/AndroidBuild.java b/app/src/processing/mode/android/AndroidBuild.java index 539d01854..7c7a3df28 100644 --- a/app/src/processing/mode/android/AndroidBuild.java +++ b/app/src/processing/mode/android/AndroidBuild.java @@ -90,9 +90,10 @@ class AndroidBuild extends JavaBuild { if (pkg.startsWith("org.json.")) return true; if (pkg.startsWith("org.w3c.dom.")) return true; if (pkg.startsWith("org.xml.sax.")) return true; - + if (pkg.startsWith("processing.core.")) return true; if (pkg.startsWith("processing.data.")) return true; + if (pkg.startsWith("processing.event.")) return true; if (pkg.startsWith("processing.opengl.")) return true; return false; diff --git a/app/src/processing/mode/android/AndroidPreprocessor.java b/app/src/processing/mode/android/AndroidPreprocessor.java index 886dac7f0..fcfebebc3 100644 --- a/app/src/processing/mode/android/AndroidPreprocessor.java +++ b/app/src/processing/mode/android/AndroidPreprocessor.java @@ -184,6 +184,7 @@ public class AndroidPreprocessor extends PdePreprocessor { return new String[] { "processing.core.*", "processing.data.*", + "processing.event.*", "processing.opengl.*" }; } @@ -191,25 +192,28 @@ public class AndroidPreprocessor extends PdePreprocessor { @Override public String[] getDefaultImports() { - final String prefsLine = Preferences.get("android.preproc.imports.list"); + final String prefsLine = Preferences.get("android.preproc.imports"); if (prefsLine != null) { return PApplet.splitTokens(prefsLine, ", "); } + // The initial values are stored in here for the day when Android + // is broken out as a separate mode. + // In the future, this may include standard classes for phone or // accelerometer access within the Android APIs. This is currently living // in code rather than preferences.txt because Android mode needs to // maintain its independence from the rest of processing.app. final String[] androidImports = new String[] { - "android.view.MotionEvent", "android.view.KeyEvent", - "android.graphics.Bitmap", //"java.awt.Image", +// "android.view.MotionEvent", "android.view.KeyEvent", +// "android.graphics.Bitmap", //"java.awt.Image", "java.io.*", // for BufferedReader, InputStream, etc //"java.net.*", "java.text.*", // leaving otu for now "java.util.*" // for ArrayList and friends //"java.util.zip.*", "java.util.regex.*" // not necessary w/ newer i/o }; - Preferences.set("android.preproc.imports.list", + Preferences.set("android.preproc.imports", PApplet.join(androidImports, ",")); return androidImports; diff --git a/app/src/processing/mode/java/JavaBuild.java b/app/src/processing/mode/java/JavaBuild.java index 0c42c02c0..3932bede0 100644 --- a/app/src/processing/mode/java/JavaBuild.java +++ b/app/src/processing/mode/java/JavaBuild.java @@ -521,6 +521,7 @@ public class JavaBuild { if (pkg.startsWith("processing.core.")) return true; if (pkg.startsWith("processing.data.")) return true; + if (pkg.startsWith("processing.event.")) return true; if (pkg.startsWith("processing.opengl.")) return true; // // ignore core, data, and opengl packages diff --git a/app/src/processing/mode/java/preproc/PdePreprocessor.java b/app/src/processing/mode/java/preproc/PdePreprocessor.java index 3a966d103..418ef3663 100644 --- a/app/src/processing/mode/java/preproc/PdePreprocessor.java +++ b/app/src/processing/mode/java/preproc/PdePreprocessor.java @@ -924,13 +924,14 @@ public class PdePreprocessor { return new String[] { "processing.core.*", "processing.data.*", + "processing.event.*", "processing.opengl.*" }; } public String[] getDefaultImports() { // These may change in-between (if the prefs panel adds this option) - String prefsLine = Preferences.get("preproc.imports.list"); + String prefsLine = Preferences.get("preproc.imports"); return PApplet.splitTokens(prefsLine, ", "); } diff --git a/build/shared/lib/preferences.txt b/build/shared/lib/preferences.txt index fa0c83a1a..df8a0b2fc 100644 --- a/build/shared/lib/preferences.txt +++ b/build/shared/lib/preferences.txt @@ -273,8 +273,13 @@ preproc.substitute_unicode = true # viewed in (at least) Mozilla or IE. useful when debugging the preprocessor. preproc.output_parse_tree = false -# Changed after 1.0.9 to a new name, and also includes the specific entries -preproc.imports.list = java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image,java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.* +# Changed after 2.0b6 to remove those that aren't compatible with Android, +# as we move to the new built-in event types. Also remove .list from the end +# of the name, so that the pref will reset. These are now the same imports +# as are used over on the Android side. +#preproc.imports.list = java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image,java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.* +#preproc.imports = java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.* +preproc.imports = java.io.*,java.util.* # set to the program to be used for opening HTML files, folders, etc. #launcher.linux = xdg-open diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index 4dd50344a..9931644f4 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -25,6 +25,7 @@ package processing.core; import processing.data.*; import processing.event.*; +import processing.event.Event; import processing.opengl.*; import java.applet.*; @@ -2136,8 +2137,9 @@ public class PApplet extends Applet // drawing commands can be run inside them. it can't // be before, since a call to background() would wipe // out anything that had been drawn so far. - dequeueMouseEvents(); - dequeueKeyEvents(); + dequeueEvents(); +// dequeueMouseEvents(); +// dequeueKeyEvents(); handleMethods("draw"); @@ -2353,20 +2355,106 @@ public class PApplet extends Applet ////////////////////////////////////////////////////////////// - // TODO this needs lots of cleaning +// protected Event eventQueue[] = new Event[10]; +// protected int eventCount; + + + class InternalEventQueue { + protected Event queue[] = new Event[10]; + protected int offset; + protected int count; + + synchronized void add(Event e) { + if (count == queue.length) { + queue = (Event[]) expand(queue); + } + queue[count++] = e; + } + + synchronized Event remove() { + if (offset == count) { + throw new RuntimeException("Nothing left on the event queue."); + } + Event outgoing = queue[offset++]; + if (offset == count) { + // All done, time to reset + offset = 0; + count = 0; + } + return outgoing; + } + + synchronized boolean available() { + return count != 0; + } + } + + InternalEventQueue eventQueue = new InternalEventQueue(); + + + /** + * Add an event to the internal event queue, or process it immediately if + * the sketch is not currently looping. + */ public void postEvent(processing.event.Event pe) { - if (pe instanceof MouseEvent) { - if (looping) { - enqueueMouseEvent((MouseEvent) pe); - } else { - handleMouseEvent((MouseEvent) pe); - } - } else if (pe instanceof KeyEvent) { - if (looping) { - enqueueKeyEvent((KeyEvent) pe); - } else { - handleKeyEvent((KeyEvent) pe); +// if (pe instanceof MouseEvent) { +//// switch (pe.getFlavor()) { +//// case Event.MOUSE: +// if (looping) { +// enqueueMouseEvent((MouseEvent) pe); +// } else { +// handleMouseEvent((MouseEvent) pe); +// enqueueEvent(pe); +// } +// } else if (pe instanceof KeyEvent) { +// if (looping) { +// enqueueKeyEvent((KeyEvent) pe); +// } else { +// handleKeyEvent((KeyEvent) pe); +// } +// } + +// synchronized (eventQueue) { +// if (eventCount == eventQueue.length) { +// eventQueue = (Event[]) expand(eventQueue); +// } +// eventQueue[eventCount++] = pe; +// } + eventQueue.add(pe); + + if (!looping) { + dequeueEvents(); + } + } + + +// protected void enqueueEvent(Event e) { +// synchronized (eventQueue) { +// if (eventCount == eventQueue.length) { +// eventQueue = (Event[]) expand(eventQueue); +// } +// eventQueue[eventCount++] = e; +// } +// } + + protected void dequeueEvents() { + // can't do this.. thread lock +// synchronized (eventQueue) { +// for (int i = 0; i < eventCount; i++) { +// Event e = eventQueue[i]; + while (eventQueue.available()) { + Event e = eventQueue.remove(); + + switch (e.getFlavor()) { + case Event.MOUSE: + handleMouseEvent((MouseEvent) e); + break; + case Event.KEY: + handleKeyEvent((KeyEvent) e); + break; } +// } +// eventCount = 0; } } @@ -2374,28 +2462,28 @@ public class PApplet extends Applet ////////////////////////////////////////////////////////////// - MouseEvent mouseEventQueue[] = new MouseEvent[10]; - int mouseEventCount; - - protected void enqueueMouseEvent(MouseEvent e) { - synchronized (mouseEventQueue) { - if (mouseEventCount == mouseEventQueue.length) { - MouseEvent temp[] = new MouseEvent[mouseEventCount << 1]; - System.arraycopy(mouseEventQueue, 0, temp, 0, mouseEventCount); - mouseEventQueue = temp; - } - mouseEventQueue[mouseEventCount++] = e; - } - } - - protected void dequeueMouseEvents() { - synchronized (mouseEventQueue) { - for (int i = 0; i < mouseEventCount; i++) { - handleMouseEvent(mouseEventQueue[i]); - } - mouseEventCount = 0; - } - } +// MouseEvent mouseEventQueue[] = new MouseEvent[10]; +// int mouseEventCount; +// +// protected void enqueueMouseEvent(MouseEvent e) { +// synchronized (mouseEventQueue) { +// if (mouseEventCount == mouseEventQueue.length) { +// MouseEvent temp[] = new MouseEvent[mouseEventCount << 1]; +// System.arraycopy(mouseEventQueue, 0, temp, 0, mouseEventCount); +// mouseEventQueue = temp; +// } +// mouseEventQueue[mouseEventCount++] = e; +// } +// } +// +// protected void dequeueMouseEvents() { +// synchronized (mouseEventQueue) { +// for (int i = 0; i < mouseEventCount; i++) { +// handleMouseEvent(mouseEventQueue[i]); +// } +// mouseEventCount = 0; +// } +// } /** @@ -2529,10 +2617,10 @@ public class PApplet extends Applet int modifiers = nativeEvent.getModifiers(); int peModifiers = modifiers & - (InputEvent.SHIFT_DOWN_MASK | - InputEvent.CTRL_DOWN_MASK | - InputEvent.META_DOWN_MASK | - InputEvent.ALT_DOWN_MASK); + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); // Windows and OS X seem to disagree on how to handle this. Windows only // sets BUTTON1_DOWN_MASK, while OS X seems to set BUTTON1_MASK. @@ -2569,12 +2657,11 @@ public class PApplet extends Applet } } - MouseEvent pe = new MouseEvent(nativeEvent, nativeEvent.getWhen(), - peAction, peModifiers, - nativeEvent.getX(), nativeEvent.getY(), - peButton, - nativeEvent.getClickCount()); - postEvent(pe); + postEvent(new MouseEvent(nativeEvent, nativeEvent.getWhen(), + peAction, peModifiers, + nativeEvent.getX(), nativeEvent.getY(), + peButton, + nativeEvent.getClickCount())); } @@ -2589,6 +2676,7 @@ public class PApplet extends Applet nativeMouseEvent(e); } + /** * @nowebref */ @@ -2596,6 +2684,7 @@ public class PApplet extends Applet nativeMouseEvent(e); } + /** * @nowebref */ @@ -2603,14 +2692,23 @@ public class PApplet extends Applet nativeMouseEvent(e); } + + /** + * @nowebref + */ public void mouseEntered(java.awt.event.MouseEvent e) { nativeMouseEvent(e); } + + /** + * @nowebref + */ public void mouseExited(java.awt.event.MouseEvent e) { nativeMouseEvent(e); } + /** * @nowebref */ @@ -2618,6 +2716,7 @@ public class PApplet extends Applet nativeMouseEvent(e); } + /** * @nowebref */ @@ -2653,6 +2752,7 @@ public class PApplet extends Applet */ public void mousePressed() { } + /** * ( begin auto-generated from mouseReleased.xml ) * @@ -2693,6 +2793,7 @@ public class PApplet extends Applet */ public void mouseClicked() { } + /** * ( begin auto-generated from mouseDragged.xml ) * @@ -2710,6 +2811,7 @@ public class PApplet extends Applet */ public void mouseDragged() { } + /** * ( begin auto-generated from mouseMoved.xml ) * @@ -2727,8 +2829,10 @@ public class PApplet extends Applet */ public void mouseMoved() { } + public void mouseEntered() { } + public void mouseExited() { } @@ -2736,29 +2840,29 @@ public class PApplet extends Applet ////////////////////////////////////////////////////////////// - KeyEvent keyEventQueue[] = new KeyEvent[10]; - int keyEventCount; - - protected void enqueueKeyEvent(KeyEvent e) { - synchronized (keyEventQueue) { - if (keyEventCount == keyEventQueue.length) { - KeyEvent temp[] = new KeyEvent[keyEventCount << 1]; - System.arraycopy(keyEventQueue, 0, temp, 0, keyEventCount); - keyEventQueue = temp; - } - keyEventQueue[keyEventCount++] = e; - } - } - - protected void dequeueKeyEvents() { - synchronized (keyEventQueue) { - for (int i = 0; i < keyEventCount; i++) { - keyEvent = keyEventQueue[i]; - handleKeyEvent(keyEvent); - } - keyEventCount = 0; - } - } +// KeyEvent keyEventQueue[] = new KeyEvent[10]; +// int keyEventCount; +// +// protected void enqueueKeyEvent(KeyEvent e) { +// synchronized (keyEventQueue) { +// if (keyEventCount == keyEventQueue.length) { +// KeyEvent temp[] = new KeyEvent[keyEventCount << 1]; +// System.arraycopy(keyEventQueue, 0, temp, 0, keyEventCount); +// keyEventQueue = temp; +// } +// keyEventQueue[keyEventCount++] = e; +// } +// } +// +// protected void dequeueKeyEvents() { +// synchronized (keyEventQueue) { +// for (int i = 0; i < keyEventCount; i++) { +// keyEvent = keyEventQueue[i]; +// handleKeyEvent(keyEvent); +// } +// keyEventCount = 0; +// } +// } // protected void handleKeyEvent(java.awt.event.KeyEvent event) { @@ -2836,13 +2940,18 @@ public class PApplet extends Applet exit(); } // When running tethered to the Processing application, respond to - // Ctrl-W (or Cmd-W) events by closing the sketch. Disable this behavior - // when running independently, because this sketch may be one component + // Ctrl-W (or Cmd-W) events by closing the sketch. Not enabled when + // running independently, because this sketch may be one component // embedded inside an application that has its own close behavior. - if (external && event.getNative() instanceof java.awt.event.KeyEvent && - ((java.awt.event.KeyEvent) event.getNative()).getModifiers() == - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() && - event.getKeyCode() == 'W') { + if (external && + event.getKeyCode() == 'W' && + ((event.isMetaDown() && platform == MACOSX) || + (event.isControlDown() && platform != MACOSX))) { + // Can't use this native stuff b/c the native event might be NEWT +// if (external && event.getNative() instanceof java.awt.event.KeyEvent && +// ((java.awt.event.KeyEvent) event.getNative()).getModifiers() == +// Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() && +// event.getKeyCode() == 'W') { exit(); } } @@ -2863,15 +2972,19 @@ public class PApplet extends Applet break; } - int peModifiers = event.getModifiersEx() & - (InputEvent.SHIFT_DOWN_MASK | - InputEvent.CTRL_DOWN_MASK | - InputEvent.META_DOWN_MASK | - InputEvent.ALT_DOWN_MASK); +// int peModifiers = event.getModifiersEx() & +// (InputEvent.SHIFT_DOWN_MASK | +// InputEvent.CTRL_DOWN_MASK | +// InputEvent.META_DOWN_MASK | +// InputEvent.ALT_DOWN_MASK); + int peModifiers = event.getModifiers() & + (InputEvent.SHIFT_MASK | + InputEvent.CTRL_MASK | + InputEvent.META_MASK | + InputEvent.ALT_MASK); - KeyEvent ke = new KeyEvent(event, event.getWhen(), peAction, peModifiers, - event.getKeyChar(), event.getKeyCode()); - postEvent(ke); + postEvent(new KeyEvent(event, event.getWhen(), peAction, peModifiers, + event.getKeyChar(), event.getKeyCode())); } @@ -2884,17 +2997,25 @@ public class PApplet extends Applet * * @nowebref */ - public void keyPressed(java.awt.event.KeyEvent e) { nativeKeyEvent(e); } + public void keyPressed(java.awt.event.KeyEvent e) { + nativeKeyEvent(e); + } + /** * @nowebref */ - public void keyReleased(java.awt.event.KeyEvent e) { nativeKeyEvent(e); } + public void keyReleased(java.awt.event.KeyEvent e) { + nativeKeyEvent(e); + } + /** * @nowebref */ - public void keyTyped(java.awt.event.KeyEvent e) { nativeKeyEvent(e); } + public void keyTyped(java.awt.event.KeyEvent e) { + nativeKeyEvent(e); + } /** diff --git a/core/src/processing/event/Event.java b/core/src/processing/event/Event.java index 3b402e088..32bf175c2 100644 --- a/core/src/processing/event/Event.java +++ b/core/src/processing/event/Event.java @@ -29,12 +29,20 @@ public class Event { protected long millis; protected int action; - static public final int SHIFT_MASK = 1 << 6; - static public final int CTRL_MASK = 1 << 7; - static public final int META_MASK = 1 << 8; - static public final int ALT_MASK = 1 << 9; + // These correspond to the java.awt.Event modifiers (not to be confused with + // the newer getModifiersEx), though they're not guaranteed to in the future. + static public final int SHIFT = 1 << 0; + static public final int CTRL = 1 << 1; + static public final int META = 1 << 2; + static public final int ALT = 1 << 3; protected int modifiers; + // Types of events. As with all constants in Processing, brevity's preferred. + static public final int KEY = 1; + static public final int MOUSE = 2; + static public final int TOUCH = 3; + protected int flavor; + public Event(Object nativeObject, long millis, int action, int modifiers) { this.nativeObject = nativeObject; @@ -44,6 +52,18 @@ public class Event { } + public int getFlavor() { + return flavor; + } + + + /** + * Get the platform-native event object. This might be the java.awt event + * on the desktop, though if you're using OpenGL on the desktop it'll be a + * NEWT event that JOGL uses. Android events are something else altogether. + * Bottom line, use this only if you know what you're doing, and don't make + * assumptions about the class type. + */ public Object getNative() { return nativeObject; } @@ -85,21 +105,21 @@ public class Event { public boolean isShiftDown() { - return (modifiers & SHIFT_MASK) != 0; + return (modifiers & SHIFT) != 0; } public boolean isControlDown() { - return (modifiers & CTRL_MASK) != 0; + return (modifiers & CTRL) != 0; } public boolean isMetaDown() { - return (modifiers & META_MASK) != 0; + return (modifiers & META) != 0; } public boolean isAltDown() { - return (modifiers & ALT_MASK) != 0; + return (modifiers & ALT) != 0; } } \ No newline at end of file diff --git a/core/src/processing/event/KeyEvent.java b/core/src/processing/event/KeyEvent.java index 90c69719d..edf89046f 100644 --- a/core/src/processing/event/KeyEvent.java +++ b/core/src/processing/event/KeyEvent.java @@ -36,6 +36,7 @@ public class KeyEvent extends Event { long millis, int action, int modifiers, char key, int keyCode) { super(nativeObject, millis, action, modifiers); + this.flavor = KEY; this.key = key; this.keyCode = keyCode; } diff --git a/core/src/processing/event/MouseEvent.java b/core/src/processing/event/MouseEvent.java index 9a727a8d3..32c4f7dd7 100644 --- a/core/src/processing/event/MouseEvent.java +++ b/core/src/processing/event/MouseEvent.java @@ -50,6 +50,7 @@ public class MouseEvent extends Event { long millis, int action, int modifiers, int x, int y, int button, int clickCount) { super(nativeObject, millis, action, modifiers); + this.flavor = MOUSE; this.x = x; this.y = y; this.button = button; diff --git a/core/src/processing/event/TouchEvent.java b/core/src/processing/event/TouchEvent.java index a5781c92d..f082e539a 100644 --- a/core/src/processing/event/TouchEvent.java +++ b/core/src/processing/event/TouchEvent.java @@ -41,5 +41,6 @@ public class TouchEvent extends Event { public TouchEvent(Object nativeObject, long millis, int action, int modifiers) { super(nativeObject, millis, action, modifiers); + this.flavor = TOUCH; } } diff --git a/core/todo.txt b/core/todo.txt index 1656ac676..edfd8c77d 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -2,6 +2,9 @@ X change to getRows() method for iterating through the Table object X add parseInto() method (provisional) X change translate() and rotate() to use x, y, z as param names +X changing default imports +X new set: java.io.*,java.net.*,java.text.*,java.util.*,java.util.zip.*,java.util.regex.* +X removed: java.applet.*,java.awt.Dimension,java.awt.Frame,java.awt.event.MouseEvent,java.awt.event.KeyEvent,java.awt.event.FocusEvent,java.awt.Image, cleaning o remove screenBlend(), textureBlend() from PGraphics et al @@ -10,7 +13,8 @@ X Support 'black' as color for SVG files (PhiLho fix) X http://code.google.com/p/processing/issues/detail?id=1010 events -_ make sure alt/ctl/meta/etc all work +_ make sure alt/ctl/meta/etc all work (for both mouse and key) +_ remove thread blocking when dequeueing events _ finish postEvent() _ need to make events interleave _ http://code.google.com/p/processing/issues/detail?id=79