changeset 6858:edeb48e251f6

Automated merge with ssh://jfxsrc.us.oracle.com//javafx/8u/master/jfx/rt
author kcr
date Thu, 24 Apr 2014 10:37:43 -0700
parents 84e1798a43a7 e52e47ec7480
children e7e9bd6d2e82
files tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxSingleTouchDevice.java
diffstat 120 files changed, 3370 insertions(+), 786 deletions(-) [+]
line wrap: on
line diff
--- a/.idea/deploy.iml	Wed Apr 23 08:35:01 2014 -0700
+++ b/.idea/deploy.iml	Thu Apr 24 10:37:43 2014 -0700
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module type="JAVA_MODULE" version="4">
   <component name="EclipseModuleManager">
-    <libelement value="jar://$MODULE_DIR$/../deploy/cache/plugin_exports.jar!/" />
+    <libelement value="jar://$MODULE_DIR$/../deploy/cache/plugin.jar!/" />
+    <libelement value="jar://$MODULE_DIR$/../deploy/cache/deploy.jar!/" />
     <src_description expected_position="0">
       <src_folder value="file://$MODULE_DIR$/../deploy/lib" expected_position="0" />
       <src_folder value="file://$MODULE_DIR$/../deploy/javafx-deploy/src" expected_position="1" />
@@ -10,35 +11,37 @@
     </src_description>
   </component>
   <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <output url="file://$MODULE_DIR$/../deploy/bin" />
     <exclude-output />
     <content url="file://$MODULE_DIR$/../deploy">
       <sourceFolder url="file://$MODULE_DIR$/../deploy/lib" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/../deploy/javafx-deploy/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/../deploy/javafx-deploy-samples/src" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/../deploy/javafx-launcher-demoapp/src" isTestSource="false" />
-      <excludeFolder url="file://$MODULE_DIR$/../deploy/javafx-deploy-samples/src/helloworld" />
+      <sourceFolder url="file://$MODULE_DIR$/../deploy/javafx-deploy/test" isTestSource="true" />
     </content>
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module-library" exported="">
-      <library name="plugin_exports.jar">
+    <orderEntry type="module" module-name="rt" />
+    <orderEntry type="module" module-name="rt-closed" />
+    <orderEntry type="module-library">
+      <library name="plugin.jar">
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/../deploy/cache/plugin_exports.jar!/" />
+          <root url="jar://$MODULE_DIR$/../deploy/cache/plugin.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES />
       </library>
     </orderEntry>
-    <orderEntry type="module" module-name="rt" exported="" />
-    <orderEntry type="inheritedJdk" />
     <orderEntry type="module-library">
-      <library>
+      <library name="deploy.jar">
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/../caches/sdk/rt/lib/ext/jfxrt.jar!/" />
+          <root url="jar://$MODULE_DIR$/../deploy/cache/deploy.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="inheritedJdk" />
   </component>
 </module>
 
--- a/.idea/modules.xml	Wed Apr 23 08:35:01 2014 -0700
+++ b/.idea/modules.xml	Thu Apr 24 10:37:43 2014 -0700
@@ -19,6 +19,7 @@
       <module fileurl="file://$PROJECT_DIR$/.idea/buildSrc.iml" filepath="$PROJECT_DIR$/.idea/buildSrc.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/builders.iml" filepath="$PROJECT_DIR$/.idea/builders.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/controls.iml" filepath="$PROJECT_DIR$/.idea/controls.iml" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/deploy.iml" filepath="$PROJECT_DIR$/.idea/deploy.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/designTime.iml" filepath="$PROJECT_DIR$/.idea/designTime.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/fxml.iml" filepath="$PROJECT_DIR$/.idea/fxml.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/fxpackager.iml" filepath="$PROJECT_DIR$/.idea/fxpackager.iml" />
--- a/apps/experiments/WebTerminal/src/webterminal/WebTerminal.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/apps/experiments/WebTerminal/src/webterminal/WebTerminal.java	Thu Apr 24 10:37:43 2014 -0700
@@ -40,8 +40,9 @@
 import org.w3c.dom.events.EventTarget;
 import netscape.javascript.JSObject;
 import javafx.application.Platform;
+import javafx.scene.control.Control;
+import javafx.scene.input.Clipboard;
 import javafx.scene.input.KeyCode;
-import javafx.scene.control.Control;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.concurrent.Worker.State;
@@ -74,16 +75,47 @@
 
     public boolean outputLFasCRLF() { return isLineEditing(); }
 
+    /** Input lines that have not been processed yet.
+     * In some modes we support enhanced type-ahead: Input lines are queued
+     * up and only released when requested.  This allows output from an
+     * earlier command, as well as prompt text for a later command, to
+     * be inserted before a later input-line.
+     */
+    Node pendingInput;
+
     /** The current input line.
      * Note there is always a current (active) input line, even if the
      * inferior isn't ready for it, and hasn't emitted a prompt.
      * This is to support type-ahead, as well as application code
-     * reading from standard input.  (FUTURE - untested.)
+     * reading from standard input.
+     * @return the currently active input line
      */
     public Element getInputLine() { return inputLine; }
     public void setInputLine(Element inputLine) { this.inputLine = inputLine; }
     Element inputLine;
 
+    public String getPendingInput() {
+	String text = null;
+	while (pendingInput != getInputLine() && text == null) {
+	    if (isSpanNode(pendingInput)) {
+		text = grabInput((Element) pendingInput);
+		if (text.length() == 0)
+		    text = null;
+	    } else if (isBreakNode(pendingInput)) {
+		text = "\n";
+	    } else if (pendingInput instanceof Text) {
+		text = ((Text) pendingInput).getData();
+		if (text.length() == 0)
+		    text = null;
+	    } else {
+		//WTDebug.println("UNEXPECTED NODE: "+WTDebug.pnode(pendingInput));
+	    }
+	    pendingInput = pendingInput.getNextSibling();
+	}
+	setOutputPosition(pendingInput);
+	return text;
+    }
+
     Document documentNode;
     Element bodyNode;
 
@@ -92,6 +124,7 @@
     /** The element (normally a div or pre) which cursor navigation is relative to.
      * Cursor motion is relative to the start of this element.
      * "Erase screen" only erases in this element.
+     * @return the cursor home location is the start of this element
      */
     public Element getCursorHome() { return cursorHome; }
     public void setCursorHome(Element cursorHome) { this.cursorHome = cursorHome; }
@@ -123,6 +156,7 @@
      * we want selection/copy to not include the inserted newline.  Better
      * would be for windows re-size to re-calculate the breaks.)
      * Initial value is true.
+     * @param value iff if we should automatically wrap
      */
     public void setWrapOnLongLines(boolean value) {
         wrapOnLongLines = value;
@@ -152,14 +186,18 @@
         currentCursorColumn = (int) (lcol >> 1) & 0x7fffffff;
     }
 
-    /** Get line of current cursor position, starting with 0 at the top. */
+    /** Get line of current cursor position.
+     * @return current line number, 0-origin (i.e. 0 is the top line),
+     *   relative to cursorHome. */
     public int getCursorLine() {
         if (currentCursorLine < 0)
             updateCursorCache();
         return currentCursorLine;
     }
 
-    /** Get column of current cursor position, starting with 0 at the left. */
+    /** Get column of current cursor position.
+     * @return current column number, 0-origin (i.e. 0 is the left column),
+     *   relative to cursorHome. */
     public int getCursorColumn() {
         if (currentCursorColumn < 0)
             updateCursorCache();
@@ -194,17 +232,20 @@
  
     /** The output position (cursor).
      * Insert output before this node.
-     * (For now always (???) equal to inputLine except for temporary updates,
-     * but in the future they may be separated.)
-     * (For now, never null, but in the future, if it is null, it means
-     * append output to the end of the output container's children.)
+     * Usually equal to inputLine except for temporary updates.
+     * @return the current output position. If null, this means append
+     * output to the end of the output container's children.
+     * (FIXME: The null case is not fully debugged.)
      */
     public Node getOutputPosition() { return outputBefore; }
     org.w3c.dom.Node outputBefore;
     public void setOutputPosition(Node node) {
         outputBefore = node; }
 
-    /** The parent node of the output position. */
+    /** The parent node of the output position.
+     * @return the output container - new output is by default inserted into
+     * this Node, at the position indicated by {@code getOutputPostion()}.
+     */
     public Node getOutputContainer() { return outputContainer; }
     Node outputContainer;
 
@@ -219,6 +260,7 @@
     protected void loadSucceeded() {
         addInputLine();
         outputBefore = inputLine;
+        pendingInput = inputLine;
     }
 
     public WebTerminal() {
@@ -251,7 +293,9 @@
     public static final String XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
     public static final String htmlNamespace = USE_XHTML ? XHTML_NAMESPACE : "";
 
-    /** URL for the initial page to be loaded. */
+    /** URL for the initial page to be loaded.
+     * @return the URL of the initial page resource as a String
+     */
     protected String pageUrl() {
         String rname = USE_XHTML ? "repl.xml" : "repl.html";
         java.net.URL rurl = WebTerminal.class.getResource(rname);
@@ -263,6 +307,7 @@
     /** Load the start page.  Do not call directly.
      * Can be overridden to load a start page from a String:
      * webEngibe.loadContent("initialContent", "MIME/type");
+     * @param webEngine the WebEngin this WebView is using.
      */
     protected void loadPage(WebEngine webEngine) {
         webEngine.load(pageUrl());
@@ -281,7 +326,9 @@
         outputContainer = initial;
     }
 
-    /** For debugging.*/
+    /** Get current contents as an HTML string. For debugging.
+     * @return the contents of teh {@code bodyNode} as HTML/XML.
+     */
     public String getHTMLText() {
         if (true) {
             return NodeWriter.writeNodeToString(bodyNode);
@@ -359,10 +406,6 @@
     }
 
     protected String handleEnter (KeyEvent ke) {
-        /*
-        javafx.scene.input.Clipboard cc = javafx.scene.input.Clipboard.getSystemClipboard();
-        System.err.println("SCLIP has-h:"+cc.hasHtml()+" has-s:"+cc.hasString()+" str:"+cc.getString());
-        */
         String text = grabInput(inputLine);
         nextInputLine();
         //super.processKeyEvent(ke);
@@ -370,11 +413,16 @@
     }
 
     protected void nextInputLine() {
+        Node outputSave = outputBefore;
+        Node containerSave = outputContainer;
+        boolean normal = outputSave == inputLine;
         outputBefore = inputLine.getNextSibling();
+        outputContainer = inputLine.getParentNode();
         setEditable(false);
         insertBreak();
         addInputLine();
-        outputBefore = inputLine;
+        outputBefore = normal ? inputLine : outputSave;
+        outputContainer = containerSave;
     }
 
     public void insertOutput (final String str, final char kind) {
@@ -1095,7 +1143,8 @@
     }
 
     /** Return column number following a tab at initial {@code col}.
-     * Both {@code col} and result are 0-origin.
+     * @param col initial column, 0-origin
+     * @return column number (0-origin) after a tab
      * Default implementation assumes tabs every 8 columns.
      */
     protected int nextTabCol(int col) {
@@ -1223,8 +1272,16 @@
                     break;
                 case '\n':
                     insertSimpleOutput(str, prevEnd, i, kind, curColumn);
-                    if (outputLFasCRLF())
-                        cursorLineStart(1);
+                    if (outputLFasCRLF()) {
+                        if (inInsertMode()) {
+                            insertRawOutput("\n");
+                            if (currentCursorLine >= 0)
+                                currentCursorLine++;
+                            currentCursorColumn = 0;
+                        } else {
+                            cursorLineStart(1);
+                        }
+                    }
                     // Only scroll if scrollRegionBottom explicitly set to a value >= 0.
                     else if (getCursorLine() == scrollRegionBottom-1)
                         scrollForward(1);
@@ -1331,12 +1388,19 @@
     }
 
     /** Insert a node at (before) current position.
-     * Caller needs to update cursor cache or call resetCursorCache. */
+     * Caller needs to update cursor cache or call resetCursorCache.
+     * @param node to be inserted at current output position.
+     *   (Should not have any parents or siblings.)
+     */
     public void insertNode (org.w3c.dom.Node node) {
         outputContainer.insertBefore(node, outputBefore);
     }
 
-    /** Insert element at current position, and move to start of element. */
+    /** Insert element at current position, and move to start of element.
+     * @param element to be inserted at current output position.
+     *  This element should have no parents *or* children.
+     *  It becomes the new outputContainer.
+     */
     public void pushIntoElement(Element element) {
         resetCursorCache(); // FIXME - not needed if element is span, say.
         insertNode(element);
@@ -1453,10 +1517,18 @@
                     processInputCharacters(chars);
             }
             ke.consume();
-        } else if (ke.getEventType() == KeyEvent.KEY_TYPED
-                   && "\r".equals(ke.getCharacter())) {
-            enter(ke);
-            ke.consume();
+        } else {
+            if (ke.getEventType() == KeyEvent.KEY_TYPED
+                && "\r".equals(ke.getCharacter())) {
+                enter(ke);
+                ke.consume();
+            } else if (ke.getEventType() == KeyEvent.KEY_PRESSED && code == KeyCode.V && ke.isControlDown()) {
+                javafx.scene.input.Clipboard cc = javafx.scene.input.Clipboard.getSystemClipboard();
+                System.err.println("SCLIP has-h:"+cc.hasHtml()+" has-s:"+cc.hasString()+" str:"+cc.getString());
+                //ke.consume();
+            } else {
+                //WTDebug.println("handle "+ke+" char:"+WTDebug.toQuoted(ke.getCharacter())+" code:"+ke.getCode());
+            }
         }
     }
 
@@ -1473,7 +1545,13 @@
 
     /** True if an img/object/a element.
      * These are treated as black boxes similar to a single
-     * 1-column character. */
+     * 1-column character.
+     * @param node an Element we want to check
+     * @return true iff the {@code node} shoudl be treated as a
+     *  block-box embedded object.
+     *  For now returns true for {@code img}, {@code a}, and {@code object}.
+     *  (We should perhaps treat {@code a} as text.)
+     */
     public boolean isObjectElement(Element node) {
         String tag = node.getTagName();
         return "a".equals(tag) || "object".equals(tag) || "img".equals(tag);
@@ -1497,13 +1575,20 @@
         return "span".equals(tag);
     }
 
-    /** Move forwards relative to cursorHome. */
+    /** Move forwards relative to cursorHome.
+     * Add spaces as needed.
+     * @param goalLine number of lines (non-negative) to move down from startNode
+     * @param goalColumn number of columns to move right from the start of teh goalLine
+     */
     public void moveTo(int goalLine, int goalColumn) {
         moveTo(cursorHome, goalLine, goalColumn, true);
     }
 
     /** Move forwards relative to startNode.
-     * Currently, assumes startNode==cursorHome; that may change.
+     * @param startNode the origin (zero) location - usually this is {@code cursorHome}
+     * @param goalLine number of lines (non-negative) to move down from startNode
+     * @param goalColumn number of columns to move right from the start of teh goalLine
+     * @param addSpaceAsNeeded if we should add blank linesor spaces if needed to move as requested; otherwise stop at the last existing line, or (just past the) last existing contents of the goalLine
      */
     public void moveTo(Node startNode, int goalLine, int goalColumn, boolean addSpaceAsNeeded) {
         //WTDebug.println("move start:"+WTDebug.pnode(startNode)+" gl:"+goalLine+" gc:"+goalColumn+" inputL:"+WTDebug.pnode(inputLine));
@@ -1707,7 +1792,7 @@
     }
 
     /** Returns number of columns needed for argument.
-     * Currently always returns 1.
+     * Currently always returns 1 (except for 'zero width space').
      * However, in the future we should handle zero-width characters
      * as well as double-width characters, and composing charcters.
      */
@@ -1725,6 +1810,12 @@
      * initial part of a compound character, including a start surrogate.
      * Compound character support is not implemented yet,
      * nor is support for zero-width or double-width characters.
+     * @param ch the next character to output
+     * @param startState the column state before emitting {@code ch}
+     *   This is basically the number of columns, but in the future we
+     *   might use the high-order bits for flags, fractional columns etc.
+     * @return the column state after {@code ch} is appended,
+     *  or -1 after a character that starts a new line
      */
     protected int updateColumn(char ch, int startState) {
         if (ch == '\n' || ch == '\r' || ch == '\f')
--- a/apps/toys/Hello/src/main/java/hello/HelloTitledPane.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/apps/toys/Hello/src/main/java/hello/HelloTitledPane.java	Thu Apr 24 10:37:43 2014 -0700
@@ -35,7 +35,9 @@
 import javafx.scene.control.TitledPane;
 import javafx.scene.layout.GridPane;
 import javafx.scene.layout.HBox;
+import javafx.scene.layout.StackPane;
 import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
 import javafx.stage.Stage;
 
 public class HelloTitledPane extends Application {
@@ -60,39 +62,43 @@
         grid.add(new TextField(), 1, 1);
         grid.add(new Label("Email: "), 0, 2);
         grid.add(new TextField(), 1, 2);
-        gridTitlePane.setText("Grid");
+        gridTitlePane.setText("Hello World!");
         gridTitlePane.setContent(grid);
         
         // --- Label test
         TitledPane normalText = new TitledPane();
         Label lbl = new Label("This is a collapsible TitledPane\nthat allows for text to be wrapped.\n\nIt should be the perfect height to fit all text provided.\n\nIs it?");
-        normalText.setText("NORMAL");
+        normalText.setText("Hello World!");
+        normalText.setFont(Font.font(20));
         normalText.setContent(lbl);
         
         // --- Big button test
         TitledPane normal = new TitledPane();
         Button bn = new Button("Button");
         bn.setPrefSize(75, 50);
-        normal.setText("NORMAL");
-        normal.setContent(bn);
+        StackPane pane = new StackPane(bn);
+        pane.setPadding(new Insets(5));
+        normal.setText("Hello World!");
+        normal.setFont(Font.font(5));
+        normal.setContent(pane);
 
         TitledPane unanimated = new TitledPane();
         unanimated.setAnimated(false);
-        unanimated.setText("NOT ANIMATED");
+        unanimated.setText("Not Animated");
         Button bs = new Button("Button");
         bs.setPrefSize(75, 50);
         unanimated.setContent(bs);
 
         TitledPane uncollapsible = new TitledPane();
         uncollapsible.setCollapsible(false);
-        uncollapsible.setText("NOT COLLAPSIBLE");
+        uncollapsible.setText("Not Collapsible");
         Button bf = new Button("Button");
         bf.setPrefSize(75, 50);
         uncollapsible.setContent(bf);
         
         HBox hbox = new HBox(10);
         hbox.setPadding(new Insets(20, 0, 0, 20));
-        hbox.getChildren().setAll(gridTitlePane, normalText, normal, unanimated, uncollapsible);
+        hbox.getChildren().setAll(normal, gridTitlePane, normalText, unanimated, uncollapsible);
 
         Group root = (Group)scene.getRoot();
         root.getChildren().add(hbox);
--- a/modules/base/src/main/java/com/sun/javafx/binding/ExpressionHelper.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/main/java/com/sun/javafx/binding/ExpressionHelper.java	Thu Apr 24 10:37:43 2014 -0700
@@ -136,7 +136,7 @@
             try {
                 listener.invalidated(observable);
             } catch (Exception e) {
-                PlatformLogger.getLogger("beans").warning("Exception in InvalidationListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -181,7 +181,7 @@
                 try {
                     listener.changed(observable, oldValue, currentValue);
                 } catch (Exception e) {
-                    PlatformLogger.getLogger("beans").warning("Exception in ChangeListener", e);
+                    Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                 }
             }
         }
@@ -348,7 +348,7 @@
                     try {
                         curInvalidationList[i].invalidated(observable);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("beans").warning("Exception in InvalidationListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
                 if (curChangeSize > 0) {
@@ -360,7 +360,7 @@
                             try {
                                 curChangeList[i].changed(observable, oldValue, currentValue);
                             } catch (Exception e) {
-                                PlatformLogger.getLogger("beans").warning("Exception in ChangeListener", e);
+                                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                             }
                         }
                     }
--- a/modules/base/src/main/java/com/sun/javafx/collections/ArrayListenerHelper.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/main/java/com/sun/javafx/collections/ArrayListenerHelper.java	Thu Apr 24 10:37:43 2014 -0700
@@ -130,7 +130,7 @@
             try {
                 listener.invalidated(observable);
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -169,7 +169,7 @@
             try {
                 listener.onChanged(observable, sizeChanged, from, to);
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in ArrayChangeListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -329,14 +329,14 @@
                     try {
                         curInvalidationList[i].invalidated(observable);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
                 for (int i = 0; i < curChangeSize; i++) {
                     try {
                         curChangeList[i].onChanged(observable, sizeChanged, from, to);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in ArrayChangeListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
             } finally {
--- a/modules/base/src/main/java/com/sun/javafx/collections/ListListenerHelper.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/main/java/com/sun/javafx/collections/ListListenerHelper.java	Thu Apr 24 10:37:43 2014 -0700
@@ -125,7 +125,7 @@
             try {
             listener.invalidated(change.getList());
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -163,7 +163,7 @@
             try {
                 listener.onChanged(change);
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in ListChangeListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -320,7 +320,7 @@
                     try {
                         curInvalidationList[i].invalidated(change.getList());
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
                 for (int i = 0; i < curChangeSize; i++) {
@@ -328,7 +328,7 @@
                     try {
                         curChangeList[i].onChanged(change);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in ListChangeListenerListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
             } finally {
--- a/modules/base/src/main/java/com/sun/javafx/collections/MapListenerHelper.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/main/java/com/sun/javafx/collections/MapListenerHelper.java	Thu Apr 24 10:37:43 2014 -0700
@@ -124,7 +124,7 @@
             try {
                 listener.invalidated(change.getMap());
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -162,7 +162,7 @@
             try {
                 listener.onChanged(change);
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in MapChangeListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -319,14 +319,14 @@
                     try {
                         curInvalidationList[i].invalidated(change.getMap());
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
                 for (int i = 0; i < curChangeSize; i++) {
                     try {
                         curChangeList[i].onChanged(change);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in MapChangeListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
             } finally {
--- a/modules/base/src/main/java/com/sun/javafx/collections/SetListenerHelper.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/main/java/com/sun/javafx/collections/SetListenerHelper.java	Thu Apr 24 10:37:43 2014 -0700
@@ -124,7 +124,7 @@
             try {
                 listener.invalidated(change.getSet());
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -162,7 +162,7 @@
             try {
                 listener.onChanged(change);
             } catch (Exception e) {
-                PlatformLogger.getLogger("collections").warning("Exception in SetChangeListener", e);
+                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
             }
         }
     }
@@ -319,14 +319,14 @@
                     try {
                         curInvalidationList[i].invalidated(change.getSet());
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in InvalidationListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
                 for (int i = 0; i < curChangeSize; i++) {
                     try {
                         curChangeList[i].onChanged(change);
                     } catch (Exception e) {
-                        PlatformLogger.getLogger("collections").warning("Exception in SetChangeListener", e);
+                        Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                     }
                 }
             } finally {
--- a/modules/base/src/test/java/com/sun/javafx/binding/ExpressionHelperTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/test/java/com/sun/javafx/binding/ExpressionHelperTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -38,7 +38,10 @@
 import org.junit.Test;
 
 import java.util.BitSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class ExpressionHelperTest {
@@ -570,4 +573,74 @@
         assertTrue(called.get(3));
     }
 
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+
+        helper = ExpressionHelper.addListener(helper, observable,(o) -> {throw new RuntimeException();});
+        observable.set(null);
+        helper.fireValueChangedEvent();
+
+        assertTrue(called.get());
+    }
+
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();});
+        helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();});
+        observable.set(null);
+        helper.fireValueChangedEvent();
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+        helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();});
+        observable.set(null);
+        helper.fireValueChangedEvent();
+
+        assertTrue(called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();});
+        helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> {throw new RuntimeException();});
+        observable.set(null);
+        helper.fireValueChangedEvent();
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> { throw new RuntimeException();});
+        helper = ExpressionHelper.addListener(helper, observable, (value, o1, o2) -> { throw new RuntimeException();});
+        helper = ExpressionHelper.addListener(helper, observable, (o) -> { throw new RuntimeException();});
+        helper = ExpressionHelper.addListener(helper, observable, (o) -> {throw new RuntimeException();});
+        observable.set(null);
+        helper.fireValueChangedEvent();
+
+        assertEquals(4, called.get());
+    }
+
 }
--- a/modules/base/src/test/java/com/sun/javafx/collections/ListListenerHelperTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/test/java/com/sun/javafx/collections/ListListenerHelperTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -39,7 +39,10 @@
 import org.junit.Test;
 
 import java.util.BitSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -670,4 +673,69 @@
         assertTrue(called.get(3));
     }
 
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+
+        helper = ListListenerHelper.addListener(helper,(Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+        helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();});
+        helper = ListListenerHelper.addListener(helper, (ListChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();});
+        helper = ListListenerHelper.addListener(helper, (Observable o) -> { throw new RuntimeException();});
+        helper = ListListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(4, called.get());
+    }
+
 }
--- a/modules/base/src/test/java/com/sun/javafx/collections/MapListenerHelperTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/test/java/com/sun/javafx/collections/MapListenerHelperTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -36,6 +36,8 @@
 import org.junit.Test;
 
 import java.util.BitSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -668,4 +670,71 @@
         assertTrue(called.get(2));
         assertTrue(called.get(3));
     }
+
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+
+        helper = MapListenerHelper.addListener(helper,(Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = MapListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper = MapListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+        helper = MapListenerHelper.addListener(helper, (MapChangeListener.Change<? extends Object, ? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = MapListenerHelper.addListener(helper, (MapChangeListener.Change<? extends Object, ? extends Object> c) -> {throw new RuntimeException();});
+        helper = MapListenerHelper.addListener(helper, (MapChangeListener.Change<? extends Object, ? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = MapListenerHelper.addListener(helper, (MapChangeListener.Change<? extends Object, ? extends Object> c) -> { throw new RuntimeException();});
+        helper = MapListenerHelper.addListener(helper, (MapChangeListener.Change<? extends Object, ? extends Object> c) -> { throw new RuntimeException();});
+        helper = MapListenerHelper.addListener(helper, (Observable o) -> { throw new RuntimeException();});
+        helper = MapListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(4, called.get());
+    }
+
 }
--- a/modules/base/src/test/java/com/sun/javafx/collections/SetListenerHelperTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/base/src/test/java/com/sun/javafx/collections/SetListenerHelperTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -38,6 +38,8 @@
 import org.junit.Test;
 
 import java.util.BitSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -672,4 +674,69 @@
     }
 
 
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleInvalidation() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+
+        helper = SetListenerHelper.addListener(helper,(Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = SetListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper = SetListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInSingleChange() {
+        AtomicBoolean called = new AtomicBoolean(false);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.set(true));
+        helper = SetListenerHelper.addListener(helper, (SetChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertTrue(called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChange() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = SetListenerHelper.addListener(helper, (SetChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper = SetListenerHelper.addListener(helper, (SetChangeListener.Change<? extends Object> c) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(2, called.get());
+    }
+
+    @Test
+    public void testExceptionHandledByThreadUncaughtHandlerInMultipleChangeAndInvalidation() {
+        AtomicInteger called = new AtomicInteger(0);
+
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> called.incrementAndGet());
+
+        helper = SetListenerHelper.addListener(helper, (SetChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();});
+        helper = SetListenerHelper.addListener(helper, (SetChangeListener.Change<? extends Object> c) -> { throw new RuntimeException();});
+        helper = SetListenerHelper.addListener(helper, (Observable o) -> { throw new RuntimeException();});
+        helper = SetListenerHelper.addListener(helper, (Observable o) -> {throw new RuntimeException();});
+        helper.fireValueChangedEvent(change);
+
+        assertEquals(4, called.get());
+    }
+
 }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java	Thu Apr 24 10:37:43 2014 -0700
@@ -466,6 +466,8 @@
         
         if (isShiftDown && getAnchor() != -1) {
             int newRow = fm.getFocusedIndex() - 1;
+            if (newRow < 0) return;
+
             int anchor = getAnchor();
             
             if (! hasAnchor()) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ToggleButtonBehavior.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/ToggleButtonBehavior.java	Thu Apr 24 10:37:43 2014 -0700
@@ -27,6 +27,7 @@
 import com.sun.javafx.scene.control.skin.Utils;
 import javafx.collections.ObservableList;
 import javafx.geometry.NodeOrientation;
+import javafx.scene.Node;
 import javafx.scene.control.Control;
 import javafx.scene.control.Toggle;
 import javafx.scene.control.ToggleButton;
@@ -75,18 +76,24 @@
                 if (Utils.isTwoLevelFocus()) {
                     super.callAction(toggleToTraverseAction(name));
                 } else if (traversingToNext) {
-                    if (currentToggleIdx == toggles.size() - 1) {
+                    int nextToggleIndex = currentToggleIdx;
+                    Toggle toggle = null;
+                    while (++nextToggleIndex < toggles.size() && (toggle = toggles.get(nextToggleIndex)) instanceof Node &&
+                            ((Node)toggle).isDisabled());
+                    if (nextToggleIndex == toggles.size()) {
                         super.callAction(toggleToTraverseAction(name));
                     } else {
-                        Toggle toggle = toggles.get(currentToggleIdx + 1);
                         toggleGroup.selectToggle(toggle);
                         ((Control)toggle).requestFocus();
                     }
                 } else {
-                    if (currentToggleIdx == 0) {
+                    int prevToggleIndex = currentToggleIdx;
+                    Toggle toggle = null;
+                    while (--prevToggleIndex >= 0 && (toggle = toggles.get(prevToggleIndex)) instanceof Node &&
+                            ((Node)toggle).isDisabled());
+                    if (prevToggleIndex < 0) {
                         super.callAction(toggleToTraverseAction(name));
                     } else {
-                        Toggle toggle = toggles.get(currentToggleIdx - 1);
                         toggleGroup.selectToggle(toggle);
                         ((Control)toggle).requestFocus();
                     }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TreeViewBehavior.java	Thu Apr 24 10:37:43 2014 -0700
@@ -413,6 +413,8 @@
         
         if (isShiftDown && getAnchor() != -1) {
             int newRow = fm.getFocusedIndex() - 1;
+            if (newRow < 0) return;
+            
             int anchor = getAnchor();
             
             if (! hasAnchor()) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxListViewSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -43,6 +43,7 @@
 import javafx.scene.Parent;
 import javafx.scene.accessibility.Attribute;
 import javafx.scene.control.ComboBox;
+import javafx.scene.control.ComboBoxBase;
 import javafx.scene.control.ListCell;
 import javafx.scene.control.ListView;
 import javafx.scene.control.SelectionMode;
@@ -98,6 +99,23 @@
     
     private final WeakListChangeListener<T> weakListViewItemsListener =
             new WeakListChangeListener<T>(listViewItemsListener);
+
+    private EventHandler<KeyEvent> textFieldKeyEventHandler = event -> {
+        if (textField == null || ! getSkinnable().isEditable()) return;
+        handleKeyEvent(event, true);
+    };
+    private EventHandler<MouseEvent> textFieldMouseEventHandler = event -> {
+        ComboBoxBase<T> comboBox = getSkinnable();
+        if (event.getTarget().equals(comboBox)) return;
+        comboBox.fireEvent(event.copyFor(comboBox, comboBox));
+        event.consume();
+    };
+    private EventHandler<DragEvent> textFieldDragEventHandler = event -> {
+        ComboBoxBase<T> comboBox = getSkinnable();
+        if (event.getTarget().equals(comboBox)) return;
+        comboBox.fireEvent(event.copyFor(comboBox, comboBox));
+        event.consume();
+    };
     
     
     
@@ -144,7 +162,7 @@
         });
 
         comboBox.addEventFilter(KeyEvent.ANY, ke -> {
-            if (textField == null) {
+            if (textField == null || ! comboBox.isEditable()) {
                 handleKeyEvent(ke, false);
             } else {
                 // This prevents a stack overflow from our rebroadcasting of the
@@ -160,27 +178,7 @@
             }
         });
 
-        if (textField != null) {
-            textField.addEventFilter(KeyEvent.ANY, ke -> {
-                if (textField == null) return;
-                handleKeyEvent(ke, true);
-            });
-        }
-
-        // Fix for RT-31093 - drag events from the textfield were not surfacing
-        // properly for the ComboBox.
-        if (textField != null) {
-            textField.addEventFilter(MouseEvent.DRAG_DETECTED, event -> {
-                if (event.getTarget().equals(comboBox)) return;
-                comboBox.fireEvent(event.copyFor(comboBox, comboBox));
-                event.consume();
-            });
-            textField.addEventFilter(DragEvent.ANY, event -> {
-                if (event.getTarget().equals(comboBox)) return;
-                    comboBox.fireEvent(event.copyFor(comboBox, comboBox));
-                    event.consume();
-            });
-        }
+        updateEditable();
         
         // Fix for RT-19431 (also tested via ComboBoxListViewSkinTest)
         updateValue();
@@ -192,6 +190,7 @@
         registerChangeListener(comboBox.converterProperty(), "CONVERTER");
         registerChangeListener(comboBox.buttonCellProperty(), "BUTTON_CELL");
         registerChangeListener(comboBox.valueProperty(), "VALUE");
+        registerChangeListener(comboBox.editableProperty(), "EDITABLE");
     }
 
 
@@ -234,8 +233,33 @@
             updateButtonCell();
         } else if ("VALUE".equals(p)) {
             updateValue();
+        } else if ("EDITABLE".equals(p)) {
+            updateEditable();
         }
     }
+
+    private void updateEditable() {
+        TextField newTextField = comboBox.getEditor();
+
+        if (!comboBox.isEditable()) {
+            // remove event filters
+            if (textField != null) {
+                textField.removeEventFilter(KeyEvent.ANY, textFieldKeyEventHandler);
+                textField.removeEventFilter(MouseEvent.DRAG_DETECTED, textFieldMouseEventHandler);
+                textField.removeEventFilter(DragEvent.ANY, textFieldDragEventHandler);
+            }
+        } else if (newTextField != null) {
+            // add event filters
+            newTextField.addEventFilter(KeyEvent.ANY, textFieldKeyEventHandler);
+
+            // Fix for RT-31093 - drag events from the textfield were not surfacing
+            // properly for the ComboBox.
+            newTextField.addEventFilter(MouseEvent.DRAG_DETECTED, textFieldMouseEventHandler);
+            newTextField.addEventFilter(DragEvent.ANY, textFieldDragEventHandler);
+        }
+
+        textField = newTextField;
+    }
     
     /** {@inheritDoc} */
     @Override public Node getDisplayNode() {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/LabeledSkinBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -797,11 +797,11 @@
         final Labeled labeled = getSkinnable();
         final Node g = labeled.getGraphic();
         if (!isIgnoreGraphic()) {
-            if (labeled.getContentDisplay() == ContentDisplay.TOP
-                || labeled.getContentDisplay() == ContentDisplay.BOTTOM) {
+            ContentDisplay contentDisplay = labeled.getContentDisplay();
+            if (contentDisplay == ContentDisplay.TOP) {
                 h = g.prefHeight(-1) + labeled.getGraphicTextGap() + textBaselineOffset;
-            } else {
-                h = Math.max(textBaselineOffset, g.prefHeight(-1));
+            } else if (contentDisplay == ContentDisplay.LEFT || contentDisplay == RIGHT) {
+                h = textBaselineOffset + (g.prefHeight(-1) - text.prefHeight(-1)) / 2;
             }
         }
                 
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ListViewSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ListViewSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -153,8 +153,13 @@
             while (c.next()) {
                 if (c.wasReplaced()) {
                     // RT-28397: Support for when an item is replaced with itself (but
-                    // updated internal values that should be shown visually)
-                    itemCount = 0;
+                    // updated internal values that should be shown visually).
+                    // This code was updated for RT-36714 to not update all cells,
+                    // just those affected by the change
+                    for (int i = c.getFrom(); i < c.getTo(); i++) {
+                        flow.setCellDirty(i);
+                    }
+
                     break;
                 } else if (c.getRemovedSize() == itemCount) {
                     // RT-22463: If the user clears out an items list then we
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableColumnHeader.java	Thu Apr 24 10:37:43 2014 -0700
@@ -165,6 +165,9 @@
             changeListenerHandler.registerChangeListener(column.graphicProperty(), "TABLE_COLUMN_GRAPHIC");
 
             column.getStyleClass().addListener(weakStyleClassListener);
+
+            setId(column.getId());
+            setStyle(column.getStyle());
             updateStyleClass();
         }
     }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableRowSkinBase.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableRowSkinBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -156,6 +156,7 @@
         // --- end init bindings
 
         registerChangeListener(control.itemProperty(), "ITEM");
+        registerChangeListener(control.indexProperty(), "INDEX");
 
         if (fixedCellSizeProperty() != null) {
             registerChangeListener(fixedCellSizeProperty(), "FIXED_CELL_SIZE");
@@ -223,20 +224,16 @@
     @Override protected void handleControlPropertyChanged(String p) {
         super.handleControlPropertyChanged(p);
 
-        if ("ITEM".equals(p)) {
-            updateCells = true;
-            getSkinnable().requestLayout();
-
-            // update the index of all children cells (RT-29849).
-            // Note that we do this after the TableRow item has been updated,
-            // rather than when the TableRow index has changed (as this will be
-            // before the row has updated its item). This will result in the
-            // issue highlighted in RT-33602, where the table cell had the correct
-            // item whilst the row had the old item.
-            final int newIndex = getSkinnable().getIndex();
-            for (int i = 0, max = cells.size(); i < max; i++) {
-                cells.get(i).updateIndex(newIndex);
+        if ("INDEX".equals(p)) {
+            // Fix for RT-36661, where empty table cells were showing content, as they
+            // had incorrect table cell indices (but the table row index was correct).
+            // Note that we only do the update on empty cells to avoid the issue
+            // noted below in requestCellUpdate().
+            if (getSkinnable().isEmpty()) {
+                requestCellUpdate();
             }
+        } else if ("ITEM".equals(p)) {
+            requestCellUpdate();
         } else if ("FIXED_CELL_SIZE".equals(p)) {
             fixedCellSize = fixedCellSizeProperty().get();
             fixedCellSizeEnabled = fixedCellSize > 0;
@@ -626,6 +623,22 @@
      *                                                                         *
      **************************************************************************/
 
+    private void requestCellUpdate() {
+        updateCells = true;
+        getSkinnable().requestLayout();
+
+        // update the index of all children cells (RT-29849).
+        // Note that we do this after the TableRow item has been updated,
+        // rather than when the TableRow index has changed (as this will be
+        // before the row has updated its item). This will result in the
+        // issue highlighted in RT-33602, where the table cell had the correct
+        // item whilst the row had the old item.
+        final int newIndex = getSkinnable().getIndex();
+        for (int i = 0, max = cells.size(); i < max; i++) {
+            cells.get(i).updateIndex(newIndex);
+        }
+    }
+
     private void recreateCells() {
         // This function is smart in the sense that we don't recreate all
         // TableCell instances every time this function is called. Instead we
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TableViewSkinBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -161,7 +161,6 @@
     protected void init(final C control) {
         // init the VirtualFlow
         flow.setPannable(IS_PANNABLE);
-        flow.setFocusTraversable(control.isFocusTraversable());
         flow.setCreateCell(flow1 -> TableViewSkinBase.this.createCell());
         
         /*
@@ -217,7 +216,6 @@
 
         registerChangeListener(rowFactoryProperty(), "ROW_FACTORY");
         registerChangeListener(placeholderProperty(), "PLACEHOLDER");
-        registerChangeListener(control.focusTraversableProperty(), "FOCUS_TRAVERSABLE");
         registerChangeListener(control.widthProperty(), "WIDTH");
         registerChangeListener(flow.getVbar().visibleProperty(), "VBAR_VISIBLE");
     }
@@ -246,7 +244,17 @@
         while (c.next()) {
             if (c.wasReplaced()) {
                 // RT-28397: Support for when an item is replaced with itself (but
-                // updated internal values that should be shown visually)
+                // updated internal values that should be shown visually).
+
+                // The ListViewSkin equivalent code here was updated to use the
+                // flow.setDirtyCell(int) API, but it was left alone here, otherwise
+                // our unit test for RT-36220 fails as we do not handle the case
+                // where the TableCell gets updated (only the TableRow does).
+                // Ideally we would use the dirtyCell API:
+                //
+                // for (int i = c.getFrom(); i < c.getTo(); i++) {
+                //     flow.setCellDirty(i);
+                // }
                 itemCount = 0;
                 break;
             } else if (c.getRemovedSize() == itemCount) {
@@ -375,8 +383,6 @@
             }
         } else if ("PLACEHOLDER".equals(p)) {
             updatePlaceholderRegionVisibility();
-        } else if ("FOCUS_TRAVERSABLE".equals(p)) {
-            flow.setFocusTraversable(getSkinnable().isFocusTraversable());
 //        } else if ("WIDTH".equals(p)) {
 //            tableHeaderRow.setTablePadding(getSkinnable().getInsets());
         } else if ("VBAR_VISIBLE".equals(p)) {
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TextAreaSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -1382,6 +1382,8 @@
             case LINE_FOR_OFFSET:
             case LINE_START:
             case LINE_END:
+            case BOUNDS_FOR_RANGE:
+            case OFFSET_AT_POINT:
                 Text text = getTextNode();
                 return text.accGetAttribute(attribute, parameters);
             default: return super.accGetAttribute(attribute, parameters);
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TextFieldSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -44,6 +44,7 @@
 import javafx.geometry.Rectangle2D;
 import javafx.scene.Group;
 import javafx.scene.Node;
+import javafx.scene.accessibility.Attribute;
 import javafx.scene.control.IndexRange;
 import javafx.scene.control.PasswordField;
 import javafx.scene.control.TextField;
@@ -797,4 +798,14 @@
             return txt;
         }
     }
+
+    @Override
+    protected Object accGetAttribute(Attribute attribute, Object... parameters) {
+        switch (attribute) {
+            case BOUNDS_FOR_RANGE:
+            case OFFSET_AT_POINT:
+                return textNode.accGetAttribute(attribute, parameters);
+            default: return super.accGetAttribute(attribute, parameters);
+        }
+    }
 }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TitledPaneSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TitledPaneSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -60,7 +60,6 @@
 
 public class TitledPaneSkin extends LabeledSkinBase<TitledPane, TitledPaneBehavior>  {
 
-    public static final int MIN_HEADER_HEIGHT = 22;
     public static final Duration TRANSITION_DURATION = new Duration(350.0);
 
     // caching results in poorer looking text (it is blurry), so we don't do it
@@ -91,11 +90,6 @@
             {
                 getStyleClass().setAll("content");
 
-                // RT-20266: We want to align the content container so the bottom of the content
-                // is at the bottom of the title region.  If we do not do this the
-                // content will be center aligned.
-                setAlignment(Pos.BOTTOM_CENTER);
-
                 if (content != null) {
                     getChildren().setAll(content);
                 }
@@ -217,7 +211,7 @@
             final double w, final double h) {
         
         // header
-        double headerHeight = Math.max(MIN_HEADER_HEIGHT, snapSize(titleRegion.prefHeight(-1)));
+        double headerHeight = snapSize(titleRegion.prefHeight(-1));
 
         titleRegion.resize(w, headerHeight);
         positionInArea(titleRegion, x, y,
@@ -246,7 +240,7 @@
     }
 
     @Override protected double computeMinHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
-        return Math.max(MIN_HEADER_HEIGHT, snapSize(titleRegion.prefHeight(width)));
+        return snapSize(titleRegion.prefHeight(width));
     }
 
     @Override protected double computePrefWidth(double height, double topInset, double rightInset, double bottomInset, double leftInset) {
@@ -256,7 +250,7 @@
     }
 
     @Override protected double computePrefHeight(double width, double topInset, double rightInset, double bottomInset, double leftInset) {
-        double headerHeight = Math.max(MIN_HEADER_HEIGHT, snapSize(titleRegion.prefHeight(width)));
+        double headerHeight = snapSize(titleRegion.prefHeight(width));
         double contentHeight = contentContainer.prefHeight(width) * getTransition();
         return headerHeight + snapSize(contentHeight) + topInset + bottomInset;
     }
@@ -271,7 +265,7 @@
     }
 
     double getTitledPaneHeightForAccordion() {
-        double headerHeight = Math.max(MIN_HEADER_HEIGHT, snapSize(titleRegion.prefHeight(-1)));
+        double headerHeight = snapSize(titleRegion.prefHeight(-1));
         double contentHeight = (prefHeightFromAccordion - headerHeight) * getTransition();
         return headerHeight + snapSize(contentHeight) + snappedTopInset() + snappedBottomInset();
     }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/TreeViewSkin.java	Thu Apr 24 10:37:43 2014 -0700
@@ -65,7 +65,6 @@
 
         // init the VirtualFlow
         flow.setPannable(IS_PANNABLE);
-        flow.setFocusTraversable(getSkinnable().isFocusTraversable());
         flow.setCreateCell(flow1 -> TreeViewSkin.this.createCell());
         flow.setFixedCellSize(treeView.getFixedCellSize());
         getChildren().add(flow);
@@ -102,7 +101,6 @@
         registerChangeListener(treeView.rootProperty(), "ROOT");
         registerChangeListener(treeView.showRootProperty(), "SHOW_ROOT");
         registerChangeListener(treeView.cellFactoryProperty(), "CELL_FACTORY");
-        registerChangeListener(treeView.focusTraversableProperty(), "FOCUS_TRAVERSABLE");
         registerChangeListener(treeView.fixedCellSizeProperty(), "FIXED_CELL_SIZE");
         
         updateRowCount();
@@ -124,8 +122,6 @@
             updateRowCount();
         } else if ("CELL_FACTORY".equals(p)) {
             flow.recreateCells();
-        } else if ("FOCUS_TRAVERSABLE".equals(p)) {
-            flow.setFocusTraversable(getSkinnable().isFocusTraversable());
         } else if ("FIXED_CELL_SIZE".equals(p)) {
             flow.setFixedCellSize(getSkinnable().getFixedCellSize());
         }
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/VirtualFlow.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/VirtualFlow.java	Thu Apr 24 10:37:43 2014 -0700
@@ -57,6 +57,7 @@
 import sun.util.logging.PlatformLogger;
 import java.util.AbstractList;
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.List;
 
 /**
@@ -942,6 +943,22 @@
             lastHeight = -1;
         }
 
+        if (! dirtyCells.isEmpty()) {
+            for (int count = 0; count < dirtyCells.cardinality(); count++) {
+                int index = dirtyCells.nextSetBit(0);
+                T cell = cells.get(index);
+                // updateIndex(-1) works for TableView, but breaks ListView.
+                // For now, the TableView just does not use the dirtyCells API
+//                cell.updateIndex(-1);
+                cell.requestLayout();
+                dirtyCells.clear(index);
+            }
+
+            setMaxPrefBreadth(-1);
+            lastWidth = -1;
+            lastHeight = -1;
+        }
+
         final boolean hasSizeChange = sizeChanged;
         boolean recreatedOrRebuilt = needsRebuildCells || needsRecreateCells || sizeChanged;
 
@@ -2364,6 +2381,7 @@
     private boolean needsRebuildCells = false; // when cell contents have changed
     private boolean needsCellsLayout = false;
     private boolean sizeChanged = false;
+    private final BitSet dirtyCells = new BitSet();
     
     public void reconfigureCells() {
         needsReconfigureCells = true;
@@ -2385,6 +2403,11 @@
         requestLayout();
     }
 
+    public void setCellDirty(int index) {
+        dirtyCells.set(index);
+        requestLayout();
+    }
+
     private static final double GOLDEN_RATIO_MULTIPLIER = 0.618033987;
 
     private double getPrefBreadth(double oppDimension) {
--- a/modules/controls/src/main/java/javafx/scene/chart/Axis.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/chart/Axis.java	Thu Apr 24 10:37:43 2014 -0700
@@ -83,6 +83,7 @@
 
     Text measure = new Text();
     private Orientation effectiveOrientation;
+    private double effectiveTickLabelRotation = Double.NaN;
     private Label axisLabel = new Label();
     private final Path tickMarkPath = new Path();
     private double oldLength = 0;
@@ -731,6 +732,7 @@
         // clear tick mark path elements as we will recreate
         tickMarkPath.getElements().clear();
         // do layout of axis label, tick mark lines and text
+        double effectiveLabelRotation = getEffectiveTickLabelRotation();
         if (Side.LEFT.equals(side)) {
             // offset path to make strokes snap to pixel
             tickMarkPath.setLayoutX(-0.5);
@@ -746,7 +748,7 @@
             for (TickMark<T> tick : tickMarks) {
                 tick.setPosition(getDisplayPosition(tick.getValue()));
                 positionTextNode(tick.textNode, width - getTickLabelGap() - tickMarkLength,
-                                 tick.getPosition(),getTickLabelRotation(),side);
+                                 tick.getPosition(), effectiveLabelRotation,side);
 
                 // check if position is inside bounds
                 if(tick.getPosition() >= 0 && tick.getPosition() <= Math.ceil(length)) {
@@ -771,7 +773,7 @@
             for (TickMark<T> tick : tickMarks) {
                 tick.setPosition(getDisplayPosition(tick.getValue()));
                 positionTextNode(tick.textNode, getTickLabelGap() + tickMarkLength,
-                                 tick.getPosition(),getTickLabelRotation(),side);
+                                 tick.getPosition(), effectiveLabelRotation,side);
                 // check if position is inside bounds
                 if(tick.getPosition() >= 0 && tick.getPosition() <= Math.ceil(length)) {
                     if (isTickLabelsVisible()) {
@@ -809,7 +811,7 @@
             for (TickMark<T> tick : tickMarks) {
                 tick.setPosition(getDisplayPosition(tick.getValue()));
                 positionTextNode(tick.textNode, tick.getPosition(), height - tickMarkLength - getTickLabelGap(),
-                        getTickLabelRotation(), side);
+                        effectiveLabelRotation, side);
                 // check if position is inside bounds
                 if(tick.getPosition() >= 0 && tick.getPosition() <= Math.ceil(length)) {
                     if (isTickLabelsVisible()) {
@@ -836,7 +838,7 @@
                 tick.setPosition(xPos);
 //                System.out.println("tick pos at : "+tickIndex+" = "+xPos);
                 positionTextNode(tick.textNode,xPos, tickMarkLength + getTickLabelGap(),
-                                getTickLabelRotation(),side);
+                        effectiveLabelRotation,side);
                 // check if position is inside bounds
                 if(xPos >= 0 && xPos <= Math.ceil(length)) {
                     if (isTickLabelsVisible()) {
@@ -873,23 +875,24 @@
      * @param side The side to place text next to position x,y at
      */
     private void positionTextNode(Text node, double posX, double posY, double angle, Side side) {
-        node.setLayoutX(0);
-        node.setLayoutY(0);
-        node.setRotate(angle);
-        final Bounds bounds = node.getBoundsInParent();
+        Bounds bounds = node.getLayoutBounds();
+        double tX, tY;
         if (Side.LEFT.equals(side)) {
-            node.setLayoutX(posX-bounds.getWidth()-bounds.getMinX());
-            node.setLayoutY(posY - (bounds.getHeight() / 2d) - bounds.getMinY());
+            tX = posX-bounds.getWidth()-bounds.getMinX();
+            tY = posY - (bounds.getHeight() / 2d) - bounds.getMinY();
         } else if (Side.RIGHT.equals(side)) {
-            node.setLayoutX(posX-bounds.getMinX());
-            node.setLayoutY(posY-(bounds.getHeight()/2d)-bounds.getMinY());
+            tX = posX-bounds.getMinX();
+            tY = posY-(bounds.getHeight()/2d)-bounds.getMinY();
         } else if (Side.TOP.equals(side)) {
-            node.setLayoutX(posX-(bounds.getWidth()/2d)-bounds.getMinX());
-            node.setLayoutY(posY-bounds.getHeight()-bounds.getMinY());
+            tX = posX-(bounds.getWidth()/2d)-bounds.getMinX();
+            tY = posY-bounds.getHeight()-bounds.getMinY();
         } else {
-            node.setLayoutX(posX-(bounds.getWidth()/2d)-bounds.getMinX());
-            node.setLayoutY(posY-bounds.getMinY());
+            tX = posX-(bounds.getWidth()/2d)-bounds.getMinX();
+            tY = posY-bounds.getMinY();
         }
+        node.getTransforms().setAll(
+                new Rotate(angle, tX + bounds.getWidth() + bounds.getHeight(), tY + bounds.getHeight()),
+                new Translate(tX, tY - bounds.getHeight()));
     }
 
     /**
@@ -934,7 +937,19 @@
      * @return size of tick mark label for given value
      */
     protected Dimension2D measureTickMarkSize(T value, Object range) {
-        return measureTickMarkSize(value,getTickLabelRotation());
+        return measureTickMarkSize(value, getEffectiveTickLabelRotation());
+    }
+
+    final double getEffectiveTickLabelRotation() {
+        return Double.isNaN(effectiveTickLabelRotation) ? getTickLabelRotation() : effectiveTickLabelRotation;
+    }
+
+    /**
+     *
+     * @param rotation NaN for using the tickLabelRotationProperty()
+     */
+    final void setEffectiveTickLabelRotation(double rotation) {
+        effectiveTickLabelRotation = rotation;
     }
 
     // -------------- TICKMARK INNER CLASS -----------------------------------------------------------------------------
--- a/modules/controls/src/main/java/javafx/scene/chart/CategoryAxis.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/chart/CategoryAxis.java	Thu Apr 24 10:37:43 2014 -0700
@@ -300,7 +300,7 @@
      * @return A range object that can be passed to setRange() and calculateTickValues()
      */
     @Override protected Object getRange() {
-        return new Object[]{ getCategories(), categorySpacing.get(), firstCategoryPos.get(), getTickLabelRotation() };
+        return new Object[]{ getCategories(), categorySpacing.get(), firstCategoryPos.get(), getEffectiveTickLabelRotation() };
     }
 
     /**
@@ -316,8 +316,8 @@
 //        if (categories.isEmpty()) new java.lang.Throwable().printStackTrace();
         double newCategorySpacing = (Double)rangeArray[1];
         double newFirstCategoryPos = (Double)rangeArray[2];
-        double tickLabelRotation = (Double)rangeArray[3];
-        setTickLabelRotation(tickLabelRotation);
+        setEffectiveTickLabelRotation((Double)rangeArray[3]);
+
         changeIsLocal = true;
         setCategories(FXCollections.<String>observableArrayList(categories));
         changeIsLocal = false;
--- a/modules/controls/src/main/java/javafx/scene/chart/ValueAxis.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/chart/ValueAxis.java	Thu Apr 24 10:37:43 2014 -0700
@@ -441,7 +441,7 @@
      * @return display position or Double.NaN if zero is not in current range;
      */
     @Override public double getDisplayPosition(T value) {
-        return Math.ceil(offset + ((value.doubleValue() - currentLowerBound.get()) * getScale()));
+        return Math.round(offset + ((value.doubleValue() - currentLowerBound.get()) * getScale()));
     }
 
     /**
--- a/modules/controls/src/main/java/javafx/scene/control/MultipleSelectionModelBase.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/MultipleSelectionModelBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -384,7 +384,7 @@
     }
 
     @Override public void selectIndices(int row, int... rows) {
-        if (rows == null) {
+        if (rows == null || rows.length == 0) {
             select(row);
             return;
         }
--- a/modules/controls/src/main/java/javafx/scene/control/TableCell.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TableCell.java	Thu Apr 24 10:37:43 2014 -0700
@@ -153,6 +153,18 @@
             }
         }
     };
+
+    private final InvalidationListener columnStyleListener = value -> {
+        if (getTableColumn() != null) {
+            possiblySetStyle(getTableColumn().getStyle());
+        }
+    };
+
+    private final InvalidationListener columnIdListener = value -> {
+        if (getTableColumn() != null) {
+            possiblySetId(getTableColumn().getId());
+        }
+    };
     
     private final WeakListChangeListener<TablePosition> weakSelectedListener =
             new WeakListChangeListener<>(selectedListener);
@@ -162,6 +174,10 @@
             new WeakInvalidationListener(tableRowUpdateObserver);
     private final WeakInvalidationListener weakEditingListener = 
             new WeakInvalidationListener(editingListener);
+    private final WeakInvalidationListener weakColumnStyleListener =
+            new WeakInvalidationListener(columnStyleListener);
+    private final WeakInvalidationListener weakColumnIdListener =
+            new WeakInvalidationListener(columnIdListener);
     private final WeakListChangeListener<TableColumn<S,?>> weakVisibleLeafColumnsListener =
             new WeakListChangeListener<>(visibleLeafColumnsListener);
     private final WeakListChangeListener<String> weakColumnStyleClassListener =
@@ -505,13 +521,14 @@
         }
 
         final TableView<S> tableView = getTableView();
-        if (getIndex() == -1 || tableView == null) return;
+        final TableRow<S> tableRow = getTableRow();
+        final int index = getIndex();
+        if (index == -1 || tableView == null || tableRow == null) return;
 
         final TableViewFocusModel<S> fm = tableView.getFocusModel();
         if (fm == null) return;
-        
-        boolean isFocusedNow = fm != null &&
-                            fm.isFocused(getIndex(), getTableColumn());
+
+        boolean isFocusedNow = fm != null && fm.isFocused(index, getTableColumn());
 
         setFocused(isFocusedNow);
     }
@@ -693,6 +710,18 @@
         if (oldCol != null) {
             oldCol.getStyleClass().removeListener(weakColumnStyleClassListener);
             getStyleClass().removeAll(oldCol.getStyleClass());
+
+            oldCol.idProperty().removeListener(weakColumnIdListener);
+            oldCol.styleProperty().removeListener(weakColumnStyleListener);
+
+            String id = getId();
+            String style = getStyle();
+            if (id != null && id.equals(oldCol.getId())) {
+                setId(null);
+            }
+            if (style != null && style.equals(oldCol.getStyle())) {
+                setStyle("");
+            }
         }
         
         setTableColumn(col);
@@ -700,6 +729,12 @@
         if (col != null) {
             getStyleClass().addAll(col.getStyleClass());
             col.getStyleClass().addListener(weakColumnStyleClassListener);
+
+            col.idProperty().addListener(weakColumnIdListener);
+            col.styleProperty().addListener(weakColumnStyleListener);
+
+            possiblySetId(col.getId());
+            possiblySetStyle(col.getStyle());
         }
     }
 
@@ -715,6 +750,18 @@
     private static final PseudoClass PSEUDO_CLASS_LAST_VISIBLE = 
             PseudoClass.getPseudoClass("last-visible");
 
+    private void possiblySetId(String idCandidate) {
+        if (getId() == null || getId().isEmpty()) {
+            setId(idCandidate);
+        }
+    }
+
+    private void possiblySetStyle(String styleCandidate) {
+        if (getStyle() == null || getStyle().isEmpty()) {
+            setStyle(styleCandidate);
+        }
+    }
+
 
 
     /***************************************************************************
--- a/modules/controls/src/main/java/javafx/scene/control/TableColumnBase.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TableColumnBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -269,6 +269,8 @@
      * The id of this TableColumnBase. This simple string identifier is useful 
      * for finding a specific TableColumnBase within a UI control that uses 
      * TableColumnBase instances. The default value is {@code null}.
+     *
+     * @defaultValue null
      */
     private StringProperty id;
     public final void setId(String value) { idProperty().set(value); }
@@ -291,10 +293,12 @@
      * <p>
      * Parsing this style might not be supported on some limited
      * platforms. It is recommended to use a standalone CSS file instead.
+     *
+     * @defaultValue empty string
      */
     private StringProperty style;
     public final void setStyle(String value) { styleProperty().set(value); }
-    @Override public final String getStyle() { return style == null ? null : style.get(); }
+    @Override public final String getStyle() { return style == null ? "" : style.get(); }
     public final StringProperty styleProperty() {
         if (style == null) {
             style = new SimpleStringProperty(this, "style");
--- a/modules/controls/src/main/java/javafx/scene/control/TableView.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TableView.java	Thu Apr 24 10:37:43 2014 -0700
@@ -693,13 +693,20 @@
         // RT-25679 - we select the first item in the control if there is no
         // current selection or focus on any other cell
         List<S> items = getItems();
-        MultipleSelectionModel<S> sm = getSelectionModel();
+        TableSelectionModel<S> sm = getSelectionModel();
         FocusModel<S> fm = getFocusModel();
 
         if (items != null && items.size() > 0 &&
                 sm != null && sm.isEmpty() &&
-                fm != null && fm.getFocusedIndex() == -1) {
-            sm.select(0);
+                fm != null && fm.getFocusedItem() == null) {
+            if (sm.isCellSelectionEnabled()) {
+                TableColumn<S,?> firstVisibleColumn = getVisibleLeafColumn(0);
+                if (firstVisibleColumn != null) {
+                    sm.select(0, firstVisibleColumn);
+                }
+            } else {
+                sm.select(0);
+            }
         }
     };
 
--- a/modules/controls/src/main/java/javafx/scene/control/TextArea.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TextArea.java	Thu Apr 24 10:37:43 2014 -0700
@@ -707,6 +707,8 @@
             case LINE_FOR_OFFSET: //Skin
             case LINE_START: //Skin
             case LINE_END:  //Skin
+            case BOUNDS_FOR_RANGE: //Skin
+            case OFFSET_AT_POINT: //Skin
             default: return super.accGetAttribute(attribute, parameters);
         }
     }
--- a/modules/controls/src/main/java/javafx/scene/control/TextField.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TextField.java	Thu Apr 24 10:37:43 2014 -0700
@@ -344,6 +344,8 @@
     @Override public Object accGetAttribute(Attribute attribute, Object... parameters) {
         switch (attribute) {
             case ROLE: return Role.TEXT_FIELD;
+            case BOUNDS_FOR_RANGE: //Skin
+            case OFFSET_AT_POINT: //Skin
             default: return super.accGetAttribute(attribute, parameters);
         }
     }
--- a/modules/controls/src/main/java/javafx/scene/control/TitledPane.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TitledPane.java	Thu Apr 24 10:37:43 2014 -0700
@@ -58,6 +58,13 @@
  * for this control.  Unexpected behavior will occur because the
  * TitledPane's height changes when it is opened or closed.</p>
  *
+ * <p>Note that whilst TitledPane extends from Labeled, the inherited properties
+ * are used to manipulate the TitledPane header, not the content area itself. If
+ * the intent is to modify the content area, consider using a layout container
+ * such as {@link javafx.scene.layout.StackPane} and setting your actual content
+ * inside of that. You can then manipulate the StackPane to get the layout
+ * results you are after.</p>
+ *
  * <p>Example:</p>
  * <pre><code>
  *  TitledPane t1 = new TitledPane("T1", new Button("B1"));
--- a/modules/controls/src/main/java/javafx/scene/control/ToggleButton.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/ToggleButton.java	Thu Apr 24 10:37:43 2014 -0700
@@ -154,6 +154,10 @@
                 @Override protected void invalidated() {
                     final boolean selected = get();
                     final ToggleGroup tg = getToggleGroup();
+                    // Note: these changes need to be done before selectToggle/clearSelectedToggle since
+                    // those operations change properties and can execute user code, possibly modifying selected property again
+                    pseudoClassStateChanged(PSEUDO_CLASS_SELECTED, selected);
+                    accSendNotification(Attribute.SELECTED);
                     if (tg != null) {
                         if (selected) {
                             tg.selectToggle(ToggleButton.this);
@@ -161,8 +165,6 @@
                             tg.clearSelectedToggle();
                         }
                     }
-                    pseudoClassStateChanged(PSEUDO_CLASS_SELECTED, selected);
-                    accSendNotification(Attribute.SELECTED);
                 }
 
                 @Override
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableCell.java	Thu Apr 24 10:37:43 2014 -0700
@@ -154,7 +154,19 @@
     private final InvalidationListener rootPropertyListener = observable -> {
         updateItem(-1);
     };
-    
+
+    private final InvalidationListener columnStyleListener = value -> {
+        if (getTableColumn() != null) {
+            possiblySetStyle(getTableColumn().getStyle());
+        }
+    };
+
+    private final InvalidationListener columnIdListener = value -> {
+        if (getTableColumn() != null) {
+            possiblySetId(getTableColumn().getId());
+        }
+    };
+
     private final WeakListChangeListener<TreeTablePosition<S,?>> weakSelectedListener = 
             new WeakListChangeListener<TreeTablePosition<S,?>>(selectedListener);
     private final WeakInvalidationListener weakFocusedListener = 
@@ -167,6 +179,10 @@
             new WeakListChangeListener<TreeTableColumn<S,?>>(visibleLeafColumnsListener);
     private final WeakListChangeListener<String> weakColumnStyleClassListener =
             new WeakListChangeListener<String>(columnStyleClassListener);
+    private final WeakInvalidationListener weakColumnStyleListener =
+            new WeakInvalidationListener(columnStyleListener);
+    private final WeakInvalidationListener weakColumnIdListener =
+            new WeakInvalidationListener(columnIdListener);
     private final WeakInvalidationListener weakRootPropertyListener =
             new WeakInvalidationListener(rootPropertyListener);
 
@@ -687,13 +703,31 @@
         if (oldCol != null) {
             oldCol.getStyleClass().removeListener(weakColumnStyleClassListener);
             getStyleClass().removeAll(oldCol.getStyleClass());
+
+            oldCol.idProperty().removeListener(weakColumnIdListener);
+            oldCol.styleProperty().removeListener(weakColumnStyleListener);
+
+            String id = getId();
+            String style = getStyle();
+            if (id != null && id.equals(oldCol.getId())) {
+                setId(null);
+            }
+            if (style != null && style.equals(oldCol.getStyle())) {
+                setStyle("");
+            }
         }
-        
+
         setTableColumn(col);
-        
+
         if (col != null) {
             getStyleClass().addAll(col.getStyleClass());
             col.getStyleClass().addListener(weakColumnStyleClassListener);
+
+            col.idProperty().addListener(weakColumnIdListener);
+            col.styleProperty().addListener(weakColumnStyleListener);
+
+            possiblySetId(col.getId());
+            possiblySetStyle(col.getStyle());
         }
     }
 
@@ -714,6 +748,18 @@
         return new TreeTableCellSkin<S,T>(this);
     }
 
+    private void possiblySetId(String idCandidate) {
+        if (getId() == null || getId().isEmpty()) {
+            setId(idCandidate);
+        }
+    }
+
+    private void possiblySetStyle(String styleCandidate) {
+        if (getStyle() == null || getStyle().isEmpty()) {
+            setStyle(styleCandidate);
+        }
+    }
+
 
     /***************************************************************************
      *                                                                         *
--- a/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/java/javafx/scene/control/TreeTableView.java	Thu Apr 24 10:37:43 2014 -0700
@@ -752,13 +752,20 @@
     private InvalidationListener focusedListener = observable -> {
         // RT-25679 - we select the first item in the control if there is no
         // current selection or focus on any other cell
-        MultipleSelectionModel<TreeItem<S>> sm = getSelectionModel();
+        TableSelectionModel<TreeItem<S>> sm = getSelectionModel();
         FocusModel<TreeItem<S>> fm = getFocusModel();
 
         if (getExpandedItemCount() > 0 &&
                 sm != null && sm.isEmpty() &&
-                fm != null && fm.getFocusedIndex() == -1) {
-            sm.select(0);
+                fm != null && fm.getFocusedItem() == null) {
+            if (sm.isCellSelectionEnabled()) {
+                TreeTableColumn<S,?> firstVisibleColumn = getVisibleLeafColumn(0);
+                if (firstVisibleColumn != null) {
+                    sm.select(0, firstVisibleColumn);
+                }
+            } else {
+                sm.select(0);
+            }
         }
     };
     
--- a/modules/controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css	Thu Apr 24 10:37:43 2014 -0700
@@ -362,6 +362,15 @@
     -fx-page-bullet-border: #acacac;
     -fx-page-indicator-hover-border: #accee5;
 
+    -fx-focused-text-base-color : ladder(
+        -fx-selection-bar,
+        -fx-light-text-color 45%,
+        -fx-dark-text-color 46%,
+        -fx-dark-text-color 59%,
+        -fx-mid-text-color 60%
+    );
+    -fx-focused-mark-color : -fx-focused-text-base-color ;
+
     /***************************************************************************
      *                                                                         *
      * Set the default background color for the scene                          *
@@ -1449,7 +1458,7 @@
     -fx-scale-shape: false;
 }
 .menu:focused > .right-container > .arrow {
-    -fx-background-color: white;
+    -fx-background-color: -fx-focused-mark-color;
 }
 .menu-up-arrow {
     -fx-padding: 0.666667em 0.416667em 0.0em 0.416667em;  /* 8 5 0 5 */
@@ -1540,7 +1549,7 @@
      -fx-text-fill:  -fx-text-background-color;
 }
 .menu-item:focused > .label {
-    -fx-text-fill: white;
+    -fx-text-fill: -fx-focused-text-base-color;
 }
 .menu-item > .right-container {
     -fx-padding: 0em 0em 0em 0.5em;
@@ -1554,7 +1563,7 @@
     -fx-scale-shape: false;
 }
 .radio-menu-item:focused:checked > .left-container > .radio {
-    -fx-background-color: white;
+    -fx-background-color: -fx-focused-mark-color;
 }
 .check-menu-item:checked > .left-container > .check {
     -fx-background-color: -fx-mark-color;
@@ -1562,7 +1571,7 @@
     -fx-scale-shape: false;
 }
 .check-menu-item:focused:checked > .left-container > .check {
-    -fx-background-color: white;
+    -fx-background-color: -fx-focused-mark-color;
 }
 /*******************************************************************************
  *                                                                             *
@@ -1781,14 +1790,15 @@
     /* No alternate highlighting */
     -fx-background: -fx-control-inner-background;
 }
-.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected {
-    -fx-background:  -fx-selection-bar-non-focused;
-    -fx-background-color:  -fx-background;
-}
-.combo-box-popup  > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:hover,
+.combo-box-popup > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:hover {
+    -fx-background: -fx-accent;
+    -fx-background-color: -fx-selection-bar;
+}
+.combo-box-popup  > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected,
 .combo-box-popup  > .list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected:hover {
     -fx-background: -fx-accent;
-    -fx-background-color: -fx-selection-bar;
+    -fx-background-color: -fx-background, -fx-cell-focus-inner-border, -fx-background;
+    -fx-background-insets: 0, 1, 2;
 }
 .combo-box-popup > .list-view > .placeholder > .label {
     -fx-text-fill: derive(-fx-control-inner-background,-30%);
--- a/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/com/sun/javafx/scene/control/infrastructure/VirtualFlowTestUtils.java	Thu Apr 24 10:37:43 2014 -0700
@@ -392,7 +392,7 @@
         return scrollBar;
     }
 
-    public static TableColumnHeader getTableColumnHeader(Control table, TableColumn<?,?> column) {
+    public static TableColumnHeader getTableColumnHeader(Control table, TableColumnBase<?,?> column) {
         TableHeaderRow headerRow = VirtualFlowTestUtils.getTableHeaderRow(table);
         return findColumnHeader(headerRow.getRootHeader(), column);
     }
--- a/modules/controls/src/test/java/javafx/scene/control/AccordionTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/AccordionTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -176,7 +176,7 @@
                                          0;
         
         assertEquals(expectedPrefWidth, accordion.prefWidth(-1), 1e-100);
-        assertEquals(66, accordion.prefHeight(-1), 1e-100);
+        assertEquals(60, accordion.prefHeight(-1), 1e-100);
 
         accordion.setExpandedPane(b);
         root.applyCss();
@@ -186,7 +186,7 @@
         assertEquals(expectedPrefWidth, accordion.prefWidth(-1), 1e-100);
         
         final double expectedPrefHeight = PlatformImpl.isCaspian() ? 170 : 
-                                          PlatformImpl.isModena()  ? 167 :
+                                          PlatformImpl.isModena()  ? 161 :
                                           0;
         assertEquals(expectedPrefHeight, accordion.prefHeight(-1), 1e-100);
     }
--- a/modules/controls/src/test/java/javafx/scene/control/ComboBoxTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/ComboBoxTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -1573,4 +1573,18 @@
 
         sl.dispose();
     }
+
+    @Test public void test_rt36717() {
+        final ComboBox<String> cb = new ComboBox<>(FXCollections.observableArrayList("a", "b", "c"));
+        StageLoader sl = new StageLoader(cb);
+
+        // the stack overflow only occurs when a ComboBox changes from non-editable to editable
+        cb.setEditable(false);
+        cb.setEditable(true);
+        assertNotNull(cb.getEditor());
+        KeyEventFirer tfKeyboard = new KeyEventFirer(cb.getEditor());
+        tfKeyboard.doKeyPress(KeyCode.ENTER);   // Stack overflow here
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/ListViewKeyInputTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -47,6 +47,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class ListViewKeyInputTest {
     private ListView<String> listView;
@@ -1963,4 +1964,43 @@
         assertTrue(sm.isSelected(4));
         assertFalse(sm.isSelected(5));
     }
+
+    @Test public void test_rt36800() {
+        // get the current exception handler before replacing with our own,
+        // as ListListenerHelp intercepts the exception otherwise
+        final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
+
+        final int items = 10;
+        listView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            listView.getItems().add("Row " + i);
+        }
+
+        sm.setSelectionMode(SelectionMode.SINGLE);
+
+        sm.clearAndSelect(5);
+        assertEquals(5, getAnchor());
+        assertTrue(fm.isFocused(5));
+        assertTrue(sm.isSelected(5));
+
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
+
+        assertEquals(0, getAnchor());
+        assertTrue(fm.isFocused(0));
+        assertTrue(sm.isSelected(0));
+        assertFalse(sm.isSelected(1));
+        assertFalse(sm.isSelected(2));
+        assertFalse(sm.isSelected(3));
+        assertFalse(sm.isSelected(4));
+        assertFalse(sm.isSelected(5));
+
+        // reset the exception handler
+        Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableCellTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TableCellTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,18 +25,17 @@
 
 package javafx.scene.control;
 
-import javafx.beans.property.ReadOnlyObjectWrapper;
-import javafx.beans.value.ObservableValue;
+import com.sun.javafx.scene.control.infrastructure.StageLoader;
+import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
-import javafx.util.Callback;
 
-import com.sun.javafx.tk.Toolkit;
 import org.junit.Before;
 import org.junit.Test;
 
 import static com.sun.javafx.scene.control.infrastructure.ControlTestUtils.assertStyleClassContains;
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 /**
  */
@@ -194,4 +193,107 @@
         table.setItems(null);
         cell.updateIndex(1);
     }
+
+    @Test public void test_rt36715_idIsNullAtStartup() {
+        assertNull(cell.getId());
+    }
+
+    @Test public void test_rt36715_idIsSettable() {
+        cell.setId("test-id");
+        assertEquals("test-id", cell.getId());
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, true, false, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, false, false, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, true, false, false, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, false, false, false, true);
+    }
+
+    @Test public void test_rt36715_styleIsEmptyStringAtStartup() {
+        assertEquals("", cell.getStyle());
+    }
+
+    @Test public void test_rt36715_styleIsSettable() {
+        cell.setStyle("-fx-border-color: red");
+        assertEquals("-fx-border-color: red", cell.getStyle());
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, true, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, true, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, false, true);
+    }
+
+    private void test_rt36715_cellPropertiesMirrorTableColumnProperties(
+            boolean setId, boolean setIdBeforeHeaderInstantiation,
+            boolean setStyle, boolean setStyleBeforeHeaderInstantiation,
+            boolean setValueOnCell) {
+
+        TableColumn column = new TableColumn("Column");
+        table.getColumns().add(column);
+
+        if (setId && setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        StageLoader sl = new StageLoader(table);
+        TableCell cell = (TableCell) VirtualFlowTestUtils.getCell(table, 0, 0);
+
+        // the default value takes precedence over the value set in the TableColumn
+        if (setValueOnCell) {
+            if (setId) {
+                cell.setId("cell-id");
+            }
+            if (setStyle) {
+                cell.setStyle("-fx-border-color: green");
+            }
+        }
+
+        if (setId && ! setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && ! setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        if (setId) {
+            if (setValueOnCell) {
+                assertEquals("cell-id", cell.getId());
+            } else {
+                assertEquals("test-id", cell.getId());
+            }
+        }
+        if (setStyle) {
+            if (setValueOnCell) {
+                assertEquals("-fx-border-color: green", cell.getStyle());
+            } else {
+                assertEquals("-fx-border-color: red", cell.getStyle());
+            }
+        }
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableColumnTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TableColumnTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,6 +25,9 @@
 
 package javafx.scene.control;
 
+import com.sun.javafx.scene.control.infrastructure.StageLoader;
+import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
+import com.sun.javafx.scene.control.skin.TableColumnHeader;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.IntegerProperty;
@@ -1223,4 +1226,70 @@
 
     public interface CellFactory<S,T> extends Callback<TableColumn<S,T>, TableCell<S,T>> {
     }
+
+    @Test public void test_rt36715_idIsNullAtStartup() {
+        assertNull(column.getId());
+    }
+
+    @Test public void test_rt36715_idIsSettable() {
+        column.setId("test-id");
+        assertEquals("test-id", column.getId());
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(true, true, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(true, false, false, false);
+    }
+
+    @Test public void test_rt36715_styleIsEmptyStringAtStartup() {
+        assertEquals("", column.getStyle());
+    }
+
+    @Test public void test_rt36715_styleIsSettable() {
+        column.setStyle("-fx-border-color: red");
+        assertEquals("-fx-border-color: red", column.getStyle());
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(false, false, true, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(false, false, true, false);
+    }
+
+    private void test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(
+            boolean setId, boolean setIdBeforeHeaderInstantiation,
+            boolean setStyle, boolean setStyleBeforeHeaderInstantiation) {
+        table.getColumns().add(column);
+
+        if (setId && setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        StageLoader sl = new StageLoader(table);
+        TableColumnHeader header = VirtualFlowTestUtils.getTableColumnHeader(table, column);
+
+        if (setId && ! setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && ! setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        if (setId) {
+            assertEquals("test-id", header.getId());
+        }
+        if (setStyle) {
+            assertEquals("-fx-border-color: red", header.getStyle());
+        }
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewKeyInputTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -50,6 +50,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class TableViewKeyInputTest {
     private TableView<String> tableView;
@@ -3458,4 +3459,76 @@
         assertTrue(sm.isSelected(4, col));
         assertFalse(sm.isSelected(5, col));
     }
+
+    @Test public void test_rt36800_rowSelection() {
+        test_rt36800(false);
+    }
+
+    @Test public void test_rt36800_cellSelection() {
+        test_rt36800(true);
+    }
+
+    private void test_rt36800(boolean cellSelection) {
+        // get the current exception handler before replacing with our own,
+        // as ListListenerHelp intercepts the exception otherwise
+        final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
+
+        final int items = 10;
+        tableView.getItems().clear();
+        for (int i = 0; i < items; i++) {
+            tableView.getItems().add("Row " + i);
+        }
+
+        TableColumn<String, String> col = new TableColumn<>("Column");
+        col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue()));
+        tableView.getColumns().setAll(col);
+
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(cellSelection);
+
+        if (cellSelection) {
+            sm.clearAndSelect(5, col);
+            assertEquals(5, getAnchor().getRow());
+            assertEquals(col, getAnchor().getTableColumn());
+            assertTrue(fm.isFocused(5, col));
+            assertTrue(sm.isSelected(5, col));
+        } else {
+            sm.clearAndSelect(5);
+            assertEquals(5, getAnchor().getRow());
+            assertTrue(fm.isFocused(5));
+            assertTrue(sm.isSelected(5));
+        }
+
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
+
+        if (cellSelection) {
+            assertEquals(0, getAnchor().getRow());
+            assertEquals(col, getAnchor().getTableColumn());
+            assertTrue(fm.isFocused(0, col));
+            assertTrue(sm.isSelected(0, col));
+            assertFalse(sm.isSelected(1, col));
+            assertFalse(sm.isSelected(2, col));
+            assertFalse(sm.isSelected(3, col));
+            assertFalse(sm.isSelected(4, col));
+            assertFalse(sm.isSelected(5, col));
+        } else {
+            assertEquals(0, getAnchor().getRow());
+            assertTrue(fm.isFocused(0));
+            assertTrue(sm.isSelected(0));
+            assertFalse(sm.isSelected(1));
+            assertFalse(sm.isSelected(2));
+            assertFalse(sm.isSelected(3));
+            assertFalse(sm.isSelected(4));
+            assertFalse(sm.isSelected(5));
+        }
+
+        // reset the exception handler
+        Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TableViewTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -2906,7 +2906,15 @@
         sl.dispose();
     }
 
-    @Test public void test_rt25679() {
+    @Test public void test_rt25679_rowSelection() {
+        test_rt25679(true);
+    }
+
+    @Test public void test_rt25679_cellSelection() {
+        test_rt25679(false);
+    }
+
+    private void test_rt25679(boolean rowSelection) {
         Button focusBtn = new Button("Focus here");
 
         TableView<String> tableView = new TableView<>(FXCollections.observableArrayList("A", "B", "C"));
@@ -2914,7 +2922,8 @@
         TableColumn<String, String> tableColumn = new TableColumn<>();
         tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue()));
         tableView.getColumns().add(tableColumn);
-        SelectionModel sm = tableView.getSelectionModel();
+        TableView.TableViewSelectionModel<String> sm = tableView.getSelectionModel();
+        sm.setCellSelectionEnabled(! rowSelection);
 
         VBox vbox = new VBox(focusBtn, tableView);
 
@@ -2935,8 +2944,25 @@
         // ensure that there is a selection (where previously there was not one)
         assertEquals(sl.getStage().getScene().getFocusOwner(), tableView);
         assertTrue(tableView.isFocused());
-        assertEquals(0, sm.getSelectedIndex());
-        assertEquals("A", sm.getSelectedItem());
+
+        if (rowSelection) {
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals("A", sm.getSelectedItem());
+            assertTrue(sm.isSelected(0));
+
+            assertEquals(1, sm.getSelectedCells().size());
+            TablePosition selectedCell = sm.getSelectedCells().get(0);
+            assertEquals(0, selectedCell.getRow());
+            assertEquals(-1, selectedCell.getColumn());
+            assertNull(selectedCell.getTableColumn());
+        } else {
+            assertTrue(sm.isSelected(0, tableColumn));
+            assertEquals(1, sm.getSelectedCells().size());
+            TablePosition selectedCell = sm.getSelectedCells().get(0);
+            assertEquals(0, selectedCell.getRow());
+            assertEquals(0, selectedCell.getColumn());
+            assertEquals(tableColumn, selectedCell.getTableColumn());
+        }
 
         sl.dispose();
     }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableCellTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableCellTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,6 +25,8 @@
 
 package javafx.scene.control;
 
+import com.sun.javafx.scene.control.infrastructure.StageLoader;
+import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
 import javafx.beans.InvalidationListener;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.ListChangeListener;
@@ -504,4 +506,107 @@
         tree.setRoot(null);
         cell.updateIndex(1);
     }
+
+    @Test public void test_rt36715_idIsNullAtStartup() {
+        assertNull(cell.getId());
+    }
+
+    @Test public void test_rt36715_idIsSettable() {
+        cell.setId("test-id");
+        assertEquals("test-id", cell.getId());
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, true, false, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, false, false, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, true, false, false, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(true, false, false, false, true);
+    }
+
+    @Test public void test_rt36715_styleIsEmptyStringAtStartup() {
+        assertEquals("", cell.getStyle());
+    }
+
+    @Test public void test_rt36715_styleIsSettable() {
+        cell.setStyle("-fx-border-color: red");
+        assertEquals("-fx-border-color: red", cell.getStyle());
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, true, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, true, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation_setValueOnCell() {
+        test_rt36715_cellPropertiesMirrorTableColumnProperties(false, false, true, false, true);
+    }
+
+    private void test_rt36715_cellPropertiesMirrorTableColumnProperties(
+            boolean setId, boolean setIdBeforeHeaderInstantiation,
+            boolean setStyle, boolean setStyleBeforeHeaderInstantiation,
+            boolean setValueOnCell) {
+
+        TreeTableColumn column = new TreeTableColumn("Column");
+        tree.getColumns().add(column);
+
+        if (setId && setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        StageLoader sl = new StageLoader(tree);
+        TreeTableCell cell = (TreeTableCell) VirtualFlowTestUtils.getCell(tree, 0, 0);
+
+        // the default value takes precedence over the value set in the TableColumn
+        if (setValueOnCell) {
+            if (setId) {
+                cell.setId("cell-id");
+            }
+            if (setStyle) {
+                cell.setStyle("-fx-border-color: green");
+            }
+        }
+
+        if (setId && ! setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && ! setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        if (setId) {
+            if (setValueOnCell) {
+                assertEquals("cell-id", cell.getId());
+            } else {
+                assertEquals("test-id", cell.getId());
+            }
+        }
+        if (setStyle) {
+            if (setValueOnCell) {
+                assertEquals("-fx-border-color: green", cell.getStyle());
+            } else {
+                assertEquals("-fx-border-color: red", cell.getStyle());
+            }
+        }
+
+        sl.dispose();
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableColumnTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableColumnTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,7 +25,9 @@
 
 package javafx.scene.control;
 
+import com.sun.javafx.scene.control.infrastructure.StageLoader;
 import com.sun.javafx.scene.control.infrastructure.VirtualFlowTestUtils;
+import com.sun.javafx.scene.control.skin.TableColumnHeader;
 import com.sun.javafx.scene.control.skin.TableViewSkin;
 import com.sun.javafx.scene.control.skin.TreeTableViewSkin;
 import com.sun.javafx.scene.control.skin.VirtualFlow;
@@ -62,6 +64,7 @@
 import org.junit.Test;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 /**
  */
@@ -1241,6 +1244,71 @@
         assertNull(cell.getText());
     }
 
+    @Test public void test_rt36715_idIsNullAtStartup() {
+        assertNull(column.getId());
+    }
+
+    @Test public void test_rt36715_idIsSettable() {
+        column.setId("test-id");
+        assertEquals("test-id", column.getId());
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdBeforeHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(true, true, false, false);
+    }
+
+    @Test public void test_rt36715_columnHeaderIdMirrorsTableColumnId_setIdAfterHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(true, false, false, false);
+    }
+
+    @Test public void test_rt36715_styleIsEmptyStringAtStartup() {
+        assertEquals("", column.getStyle());
+    }
+
+    @Test public void test_rt36715_styleIsSettable() {
+        column.setStyle("-fx-border-color: red");
+        assertEquals("-fx-border-color: red", column.getStyle());
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleBeforeHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(false, false, true, true);
+    }
+
+    @Test public void test_rt36715_columnHeaderStyleMirrorsTableColumnStyle_setStyleAfterHeaderInstantiation() {
+        test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(false, false, true, false);
+    }
+
+    private void test_rt36715_columnHeaderPropertiesMirrorTableColumnProperties(
+            boolean setId, boolean setIdBeforeHeaderInstantiation,
+            boolean setStyle, boolean setStyleBeforeHeaderInstantiation) {
+        table.getColumns().add(column);
+
+        if (setId && setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        StageLoader sl = new StageLoader(table);
+        TableColumnHeader header = VirtualFlowTestUtils.getTableColumnHeader(table, column);
+
+        if (setId && ! setIdBeforeHeaderInstantiation) {
+            column.setId("test-id");
+        }
+        if (setStyle && ! setStyleBeforeHeaderInstantiation) {
+            column.setStyle("-fx-border-color: red");
+        }
+
+        if (setId) {
+            assertEquals("test-id", header.getId());
+        }
+        if (setStyle) {
+            assertEquals("-fx-border-color: red", header.getStyle());
+        }
+
+        sl.dispose();
+    }
     
 
 
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewKeyInputTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -51,6 +51,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 public class TreeTableViewKeyInputTest {
     private TreeTableView<String> tableView;
@@ -3989,4 +3990,77 @@
         assertTrue(sm.isSelected(4, col));
         assertFalse(sm.isSelected(5, col));
     }
+
+    @Test public void test_rt36800_rowSelection() {
+        test_rt36800(false);
+    }
+
+    @Test public void test_rt36800_cellSelection() {
+        test_rt36800(true);
+    }
+
+    private void test_rt36800(boolean cellSelection) {
+        // get the current exception handler before replacing with our own,
+        // as ListListenerHelp intercepts the exception otherwise
+        final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
+
+        final int items = 10;
+        root.getChildren().clear();
+        root.setExpanded(true);
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        TreeTableColumn<String, String> col = new TreeTableColumn<>("Column");
+        col.setCellValueFactory(param -> new ReadOnlyStringWrapper(param.getValue().getValue()));
+        tableView.getColumns().setAll(col);
+
+        sm.setSelectionMode(SelectionMode.SINGLE);
+        sm.setCellSelectionEnabled(cellSelection);
+
+        if (cellSelection) {
+            sm.clearAndSelect(5, col);
+            assertEquals(5, getAnchor().getRow());
+            assertEquals(col, getAnchor().getTableColumn());
+            assertTrue(fm.isFocused(5, col));
+            assertTrue(sm.isSelected(5, col));
+        } else {
+            sm.clearAndSelect(5);
+            assertEquals(5, getAnchor().getRow());
+            assertTrue(fm.isFocused(5));
+            assertTrue(sm.isSelected(5));
+        }
+
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
+
+        if (cellSelection) {
+            assertEquals(0, getAnchor().getRow());
+            assertEquals(col, getAnchor().getTableColumn());
+            assertTrue(fm.isFocused(0, col));
+            assertTrue(sm.isSelected(0, col));
+            assertFalse(sm.isSelected(1, col));
+            assertFalse(sm.isSelected(2, col));
+            assertFalse(sm.isSelected(3, col));
+            assertFalse(sm.isSelected(4, col));
+            assertFalse(sm.isSelected(5, col));
+        } else {
+            assertEquals(0, getAnchor().getRow());
+            assertTrue(fm.isFocused(0));
+            assertTrue(sm.isSelected(0));
+            assertFalse(sm.isSelected(1));
+            assertFalse(sm.isSelected(2));
+            assertFalse(sm.isSelected(3));
+            assertFalse(sm.isSelected(4));
+            assertFalse(sm.isSelected(5));
+        }
+
+        // reset the exception handler
+        Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
+    }
 }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeTableViewTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -3282,7 +3282,15 @@
         sl.dispose();
     }
 
-    @Test public void test_rt25679() {
+    @Test public void test_rt25679_rowSelection() {
+        test_rt25679(true);
+    }
+
+    @Test public void test_rt25679_cellSelection() {
+        test_rt25679(false);
+    }
+
+    private void test_rt25679(boolean rowSelection) {
         Button focusBtn = new Button("Focus here");
 
         TreeItem<String> root = new TreeItem<>("Root");
@@ -3294,7 +3302,8 @@
         tableColumn.setCellValueFactory(rowValue -> new SimpleStringProperty(rowValue.getValue().getValue()));
         treeView.getColumns().add(tableColumn);
 
-        SelectionModel sm = treeView.getSelectionModel();
+        TreeTableView.TreeTableViewSelectionModel<String> sm = treeView.getSelectionModel();
+        sm.setCellSelectionEnabled(! rowSelection);
 
         VBox vbox = new VBox(focusBtn, treeView);
 
@@ -3315,8 +3324,25 @@
         // ensure that there is a selection (where previously there was not one)
         assertEquals(sl.getStage().getScene().getFocusOwner(), treeView);
         assertTrue(treeView.isFocused());
-        assertEquals(0, sm.getSelectedIndex());
-        assertEquals(root, sm.getSelectedItem());
+
+        if (rowSelection) {
+            assertEquals(1, sm.getSelectedIndices().size());
+            assertEquals(root, sm.getSelectedItem());
+            assertTrue(sm.isSelected(0));
+
+            assertEquals(1, sm.getSelectedCells().size());
+            TreeTablePosition selectedCell = sm.getSelectedCells().get(0);
+            assertEquals(0, selectedCell.getRow());
+            assertEquals(-1, selectedCell.getColumn());
+            assertNull(selectedCell.getTableColumn());
+        } else {
+            assertTrue(sm.isSelected(0, tableColumn));
+            assertEquals(1, sm.getSelectedCells().size());
+            TreeTablePosition selectedCell = sm.getSelectedCells().get(0);
+            assertEquals(0, selectedCell.getRow());
+            assertEquals(0, selectedCell.getColumn());
+            assertEquals(tableColumn, selectedCell.getTableColumn());
+        }
 
         sl.dispose();
     }
--- a/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/controls/src/test/java/javafx/scene/control/TreeViewKeyInputTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -50,6 +50,7 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 //@Ignore("Disabling tests as they fail with OOM in continuous builds")
 public class TreeViewKeyInputTest {
@@ -2188,4 +2189,44 @@
         assertTrue(sm.isSelected(4));
         assertFalse(sm.isSelected(5));
     }
+
+    @Test public void test_rt36800() {
+        // get the current exception handler before replacing with our own,
+        // as ListListenerHelp intercepts the exception otherwise
+        final Thread.UncaughtExceptionHandler exceptionHandler = Thread.currentThread().getUncaughtExceptionHandler();
+        Thread.currentThread().setUncaughtExceptionHandler((t, e) -> fail("We don't expect any exceptions in this test!"));
+
+        final int items = 10;
+        root.getChildren().clear();
+        root.setExpanded(true);
+        for (int i = 0; i < items; i++) {
+            root.getChildren().add(new TreeItem<>("Row " + i));
+        }
+
+        sm.setSelectionMode(SelectionMode.SINGLE);
+
+        sm.clearAndSelect(5);
+        assertEquals(5, getAnchor());
+        assertTrue(fm.isFocused(5));
+        assertTrue(sm.isSelected(5));
+
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 4
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 3
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 2
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 1
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // 0
+        keyboard.doKeyPress(KeyCode.UP, KeyModifier.SHIFT); // bug time?
+
+        assertEquals(0, getAnchor());
+        assertTrue(fm.isFocused(0));
+        assertTrue(sm.isSelected(0));
+        assertFalse(sm.isSelected(1));
+        assertFalse(sm.isSelected(2));
+        assertFalse(sm.isSelected(3));
+        assertFalse(sm.isSelected(4));
+        assertFalse(sm.isSelected(5));
+
+        // reset the exception handler
+        Thread.currentThread().setUncaughtExceptionHandler(exceptionHandler);
+    }
 }
--- a/modules/fxpackager/src/main/java/com/oracle/bundlers/AbstractBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/oracle/bundlers/AbstractBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -158,11 +158,8 @@
         return result;
     }
 
-    //For dev testing
-    public void logParameters(Map<String, ? super Object> p) {
-        Log.info("###### Parameters for " + getName());
-        for(Map.Entry<String, ? super Object> e: p.entrySet()) {
-            Log.info("    id: " + e.getKey() + " value: " + e.getValue());
-        }
+    @Override
+    public String toString() {
+        return getName();
     }
 }
--- a/modules/fxpackager/src/main/java/com/oracle/bundlers/StandardBundlerParam.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/oracle/bundlers/StandardBundlerParam.java	Thu Apr 24 10:37:43 2014 -0700
@@ -429,7 +429,7 @@
                     I18N.getString("param.preferences-id.description"),
                     "preferencesID",
                     String.class,
-                    IDENTIFIER::fetchFrom,
+                    p -> IDENTIFIER.fetchFrom(p).replace('.', '/'),
                     (s, p) -> s
             );
 
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/ant/Preferences.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/ant/Preferences.java	Thu Apr 24 10:37:43 2014 -0700
@@ -51,8 +51,8 @@
  */
 public class Preferences extends DataType {
     private boolean installRequested = false;
-    private boolean shortcutRequested = false;
-    private boolean menuRequested = false;
+    private Boolean shortcutRequested = null;
+    private Boolean menuRequested = null;
     private Boolean systemWide = null;
 
     Boolean getSystemInstall() {
@@ -80,18 +80,18 @@
     /**
      * If true then application requests desktop shortcut to be created.
      *
-     * @ant.not-required    Default is false.
+     * @ant.not-required    Default is null.
      */
-        public void setShortcut(boolean b) {
+    public void setShortcut(Boolean b) {
         shortcutRequested = b;
     }
 
     /**
      * If true then application requests to add entry to the system Start Menu.
      *
-     * @ant.not-required    Default is false.
+     * @ant.not-required    Default is null.
      */
-    public void setMenu(boolean b) {
+    public void setMenu(Boolean b) {
         menuRequested = b;
     }
 
@@ -102,11 +102,11 @@
         return this;
     }
 
-    boolean getMenu() {
+    Boolean getMenu() {
         return get().menuRequested;
     }
 
-    boolean getShortcut() {
+    Boolean getShortcut() {
         return get().shortcutRequested;
     }
 
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/DeployParams.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/DeployParams.java	Thu Apr 24 10:37:43 2014 -0700
@@ -81,8 +81,8 @@
     boolean isExtension = false;
     boolean isSwingApp = false;
 
-    boolean needShortcut = false;
-    boolean needMenu = false;
+    Boolean needShortcut = null;
+    Boolean needMenu = null;
     boolean needInstall = false;
 
     String outfile;
@@ -172,11 +172,11 @@
         offlineAllowed = b;
     }
 
-    public void setNeedShortcut(boolean b) {
+    public void setNeedShortcut(Boolean b) {
         needShortcut = b;
     }
 
-    public void setNeedMenu(boolean b) {
+    public void setNeedMenu(Boolean b) {
         needMenu = b;
     }
 
@@ -517,7 +517,7 @@
             bundleParams.setLicenseType(licenseType);
             bundleParams.setDescription(description);
             bundleParams.setTitle(title);
-            bundleParams.setVerbose(verbose);
+            if (verbose) bundleParams.setVerbose(verbose);
 
             bundleParams.setJvmProperties(properties);
             bundleParams.setJvmargs(jvmargs);
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/Main.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/Main.java	Thu Apr 24 10:37:43 2014 -0700
@@ -210,6 +210,8 @@
                             addArgument(createJarParams, nextArg(args, i++));
                         }  else if (arg.equalsIgnoreCase("-paramFile")) {
                             createJarParams.setParams(parseParams(nextArg(args, i++)));
+                        } else {
+                            throw new PackagerException("ERR_UnknownArgument", arg);
                         }
                     }
                     if (!srcfilesSet) {
@@ -261,7 +263,7 @@
                             BundleType type = BundleType.ALL;
                             String format = null; //null means ANY
                             if (i+1 < args.length && !args[i+1].startsWith("-")) {
-                                String v = args[i+1];
+                                String v = args[++i];
                                 //parsing logic is the same as in DeployFXTask
                                 if ("image".equals(v)) {
                                     type = BundleType.IMAGE;
@@ -328,6 +330,8 @@
                             srcfilesSet = true;
                         } else if (arg.equalsIgnoreCase("-argument")) {
                             addArgument(deployParams, nextArg(args, i++));
+                        } else {
+                            throw new PackagerException("ERR_UnknownArgument", arg);
                         }
                     }
                     if (templateInFile != null) {
@@ -355,6 +359,8 @@
                         } else if (arg.equalsIgnoreCase("-srcfiles")) {
                             addResources(createBssParams, srcdir, nextArg(args, i++));
                             srcfilesSet = true;
+                        } else {
+                            throw new PackagerException("ERR_UnknownArgument", arg);
                         }
                     }
                     if (!srcfilesSet) {
@@ -390,6 +396,8 @@
                         } else if (arg.equalsIgnoreCase("-srcfiles")) {
                             addResources(signJarParams, srcdir, nextArg(args, i++));
                             srcfilesSet = true;
+                        } else {
+                            throw new PackagerException("ERR_UnknownArgument", arg);
                         }
                     }
                     if (!srcfilesSet) {
@@ -417,6 +425,8 @@
                             makeAllParams.setHeight(Integer.parseInt(nextArg(args, i++)));
                         } else if(arg.equalsIgnoreCase("-v")) {
                             makeAllParams.setVerbose(true);
+                        } else {
+                            throw new PackagerException("ERR_UnknownArgument", arg);
                         }
                     }
                     makeAll = true;
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/PackagerLib.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/PackagerLib.java	Thu Apr 24 10:37:43 2014 -0700
@@ -91,7 +91,7 @@
 import static com.oracle.bundlers.StandardBundlerParam.*;
 
 public class PackagerLib {
-    public static final String JAVAFX_VERSION = "2.2";
+    public static final String JAVAFX_VERSION = "8.0";
 
     private static final ResourceBundle bundle =
             ResourceBundle.getBundle("com/sun/javafx/tools/packager/Bundle");
@@ -990,7 +990,7 @@
             out.println("</security>");
         }
 
-        if (deployParams.needShortcut) {
+        if (Boolean.TRUE.equals(deployParams.needShortcut)) {
             out.println("  <shortcut><desktop/></shortcut>");
 
 //            //TODO: Add support for a more sophisticated shortcut tag.
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/BundleParams.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/BundleParams.java	Thu Apr 24 10:37:43 2014 -0700
@@ -262,7 +262,7 @@
         return fetchParam(SHORTCUT_HINT);
     }
 
-    public void setShortcutHint(boolean v) {
+    public void setShortcutHint(Boolean v) {
         putUnlessNull(PARAM_SHORTCUT, v);
     }
 
@@ -270,7 +270,7 @@
         return fetchParam(MENU_HINT);
     }
 
-    public void setMenuHint(boolean v) {
+    public void setMenuHint(Boolean v) {
         putUnlessNull(PARAM_MENU, v);
     }
 
@@ -302,7 +302,7 @@
         return fetchParam(VERBOSE);
     }
 
-    public void setVerbose(boolean verbose) {
+    public void setVerbose(Boolean verbose) {
         putUnlessNull(VERBOSE.getID(), verbose);
     }
 
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxAppBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxAppBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -220,11 +220,6 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return getName();
-    }
-
     private void copyApplication(Map<String, ? super Object> params, File appDirectory) throws IOException {
         RelativeFileSet appResources = APP_RESOURCES.fetchFrom(params);
         if (appResources == null) {
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxDebBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxDebBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -353,11 +353,6 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return getName();
-    }
-
     private String getArch() {
         String arch = System.getProperty("os.arch");
         if ("i386".equals(arch))
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxRPMBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/LinuxRPMBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -85,9 +85,15 @@
             params -> {
                 String nm = APP_NAME.fetchFrom(params);
                 if (nm == null) return null;
-        
-                //spaces are not allowed in RPM package names
-                nm = nm.replaceAll(" ", "");
+
+                // Fedora rules are used here
+                // https://fedoraproject.org/wiki/Packaging:NamingGuidelines?rd=Packaging/NamingGuidelines
+                // The net effect is to lowercase the app name,
+                // change spaces and underscores to dashes,
+                // and to remove all alphanum+dashes
+                nm = nm.toLowerCase()
+                        .replaceAll("[ _]", "-")
+                        .replaceAll("[^-abcdefghijklmnopqrstuvwxyz0123456789]", "");
                 return nm;
             },
             (s, p) -> s);
@@ -261,11 +267,6 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return getName();
-    }
-
     private String getLicenseFileString(Map<String, ? super Object> params) {
         StringBuilder sb = new StringBuilder();
         for (String f: LICENSE_FILE.fetchFrom(params)) {
@@ -273,7 +274,7 @@
                 sb.append("\n");
             }
             sb.append("%doc /opt/");
-            sb.append(BUNDLE_NAME.fetchFrom(params));
+            sb.append(APP_NAME.fetchFrom(params));
             sb.append("/app/");
             sb.append(f);
         }
@@ -283,8 +284,8 @@
     private boolean prepareProjectConfig(Map<String, ? super Object> params) throws IOException {
         Map<String, String> data = new HashMap<>();
 
-        data.put("APPLICATION_NAME", BUNDLE_NAME.fetchFrom(params));
-        data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params).toLowerCase());
+        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
         data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
         data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
         data.put("APPLICATION_LAUNCHER_FILENAME",
@@ -392,7 +393,9 @@
         pb = pb.directory(RPM_IMAGE_DIR.fetchFrom(params));
         IOUtils.exec(pb, VERBOSE.fetchFrom(params));
 
-        IOUtils.deleteRecursive(broot);
+        if (!Log.isDebug()) {
+            IOUtils.deleteRecursive(broot);
+        }
 
         Log.info(MessageFormat.format(I18N.getString("message.output-bundle-location"), outdir.getAbsolutePath()));
 
@@ -455,8 +458,6 @@
                 IMAGES_ROOT,
                 LICENSE_FILE,
                 LICENSE_TYPE,
-                MENU_HINT,
-                SHORTCUT_HINT,
                 TITLE,
                 VENDOR,
                 VERSION
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/MacAppBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/MacAppBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -575,7 +575,7 @@
         data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params));
 //        }
         // This will be an empty string for correctly packaged JavaFX apps
-        data.put("DEPLOY_APP_CLASSPATH", MAIN_JAR_CLASSPATH.fetchFrom(params));
+        data.put("DEPLOY_APP_CLASSPATH", MAIN_JAR_CLASSPATH.fetchFrom(params).replace(":", " "));
 
         //TODO: Add remainder of the classpath
 
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/MacDMGBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/MacDMGBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -122,19 +122,6 @@
         APP_BUNDLER.fetchFrom(params).cleanupConfigFiles(params);
     }
 
-    @Override
-    public String toString() {
-        return getName();
-    }
-
-//    @Override
-//    protected void setBuildRoot(File dir) {
-//        super.setBuildRoot(dir);
-//        configRoot = new File(dir, "macosx");
-//        configRoot.mkdirs();
-//        APP_BUNDLER.fetchFrom(params).setBuildRoot(dir);
-//    }
-
     private static final String hdiutil = "/usr/bin/hdiutil";
 
     private void prepareDMGSetupScript(String volumeName, Map<String, ? super Object> p) throws IOException {
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinAppBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinAppBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -350,11 +350,6 @@
 
     }
 
-    @Override
-    public String toString() {
-        return "Windows Application Bundler";
-    }
-
     private void copyApplication(Map<String, ? super Object> params, File appDirectory) throws IOException {
         RelativeFileSet appResource = APP_RESOURCES.fetchFrom(params);
         if (appResource == null) {
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinExeBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinExeBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -402,11 +402,6 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return "Exe Bundler (based on Inno Setup)";
-    }
-
     private String getAppIdentifier(Map<String, ? super Object> params) {
         String nm = IDENTIFIER.fetchFrom(params);
 
--- a/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinMsiBundler.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/java/com/sun/javafx/tools/packager/bundlers/WinMsiBundler.java	Thu Apr 24 10:37:43 2014 -0700
@@ -471,11 +471,6 @@
                 APP_NAME.fetchFrom(params) + "-post-image.wsf");
     }
 
-    @Override
-    public String toString() {
-        return getName();
-    }
-
     private boolean prepareBasicProjectConfig(Map<String, ? super Object> params) throws IOException {
         fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX + getConfig_Script(params).getName(),
                 I18N.getString("resource.post-install-script"),
--- a/modules/fxpackager/src/main/resources/com/oracle/bundlers/StandardBundlerParam.properties	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/resources/com/oracle/bundlers/StandardBundlerParam.properties	Thu Apr 24 10:37:43 2014 -0700
@@ -68,8 +68,8 @@
 param.name.name=Name
 param.name.description=The name of the application.
 
-param.preferences-id.description=When storing and retrieving user preferences, what is the identifier that should be used?  The format should be a DNS name in reverse order, such as com.example.myapplication.
 param.preferences-id.name=Preferences ID
+param.preferences-id.description=The preferences node to search for User JVM Options.  The format be a slash delimited version of the main package name, such as "com/example/myapplication".
 
 param.runtime.name=JRE
 param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
--- a/modules/fxpackager/src/main/resources/com/oracle/bundlers/linux/LinuxAppBundler.properties	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/resources/com/oracle/bundlers/linux/LinuxAppBundler.properties	Thu Apr 24 10:37:43 2014 -0700
@@ -1,4 +1,4 @@
-bundler.name=Lunix Application Image
+bundler.name=Linux Application Image
 bundler.description=A Directory based image of a linux Application with an optionally co-bundled JRE.  Used as a base for the Installer bundlers.
 
 param.raw-executable-url.name = Launcher URL
--- a/modules/fxpackager/src/main/resources/com/sun/javafx/tools/resource/linux/template.spec	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/main/resources/com/sun/javafx/tools/resource/linux/template.spec	Thu Apr 24 10:37:43 2014 -0700
@@ -1,11 +1,11 @@
 Summary: APPLICATION_SUMMARY
-Name: APPLICATION_NAME
+Name: APPLICATION_PACKAGE
 Version: APPLICATION_VERSION
 Release: 1
 License: APPLICATION_LICENSE_TYPE
 Vendor: APPLICATION_VENDOR
 Prefix: /opt
-Provides: APPLICATION_NAME
+Provides: APPLICATION_PACKAGE
 Requires: ld-linux.so.2 libX11.so.6 libXext.so.6 libXi.so.6 libXrender.so.1 libXtst.so.6 libasound.so.2 libc.so.6 libdl.so.2 libgcc_s.so.1 libm.so.6 libpthread.so.0 libthread_db.so.1
 Autoprov: 0
 Autoreq: 0
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxAppBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxAppBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -128,6 +128,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxDebBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxDebBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -129,6 +129,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxRpmBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/linux/LinuxRpmBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -130,7 +130,9 @@
         bundleParams.put(BUILD_ROOT.getID(), tmpBase);
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
+        bundleParams.put(LinuxRPMBundler.BUNDLE_NAME.getID(), "smokeybundlename");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacAppBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacAppBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -127,6 +127,7 @@
         bundleParams.put(APP_NAME.getID(), "Smoke Test App");
         bundleParams.put(MAC_CF_BUNDLE_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
@@ -165,6 +166,7 @@
         bundleParams.put(APP_NAME.getID(), "Quarantined Test App");
         bundleParams.put(MAC_CF_BUNDLE_NAME.getID(), "Quarantine");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources));
         bundleParams.put(VERBOSE.getID(), true);
 
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacAppStoreBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacAppStoreBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -150,6 +150,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacDMGBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacDMGBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -130,6 +130,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacPKGBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/mac/MacPKGBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -129,6 +129,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources));
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
@@ -171,6 +172,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Quarantine");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(APP_RESOURCES.getID(), new RelativeFileSet(appResourcesDir, appResources));
         bundleParams.put(VERBOSE.getID(), true);
 
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinAppBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinAppBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -126,6 +126,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinEXEBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinEXEBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -133,6 +133,7 @@
 
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinMSIBundlerTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/oracle/bundlers/windows/WinMSIBundlerTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -131,6 +131,7 @@
         
         bundleParams.put(APP_NAME.getID(), "Smoke");
         bundleParams.put(MAIN_CLASS.getID(), "hello.TestPackager");
+        bundleParams.put(PREFERENCES_ID.getID(), "the/really/long/preferences/id");
         bundleParams.put(MAIN_JAR.getID(),
                 new RelativeFileSet(fakeMainJar.getParentFile(),
                         new HashSet<>(Arrays.asList(fakeMainJar)))
--- a/modules/fxpackager/src/test/java/com/sun/javafx/tools/packager/CLITest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/com/sun/javafx/tools/packager/CLITest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -69,7 +69,7 @@
     }
 
     @Test
-    public void addRuntimeBundleParam() throws Exception {
+    public void smokeParams() throws Exception {
         com.sun.javafx.tools.packager.Main.main("-deploy",
                 "-verbose", // verbose is required or test will call System.exit() on failures and break the build
                 "-srcfiles", fakeMainJar.getCanonicalPath(),
@@ -78,6 +78,9 @@
                 "-appclass", "hello.TestPackager",
                 "-native", "image",
                 "-name", "SimpleTest",
+                "-BOptionThatWillNeverExist=true",
+                "-BdesktopHint=false",
+                "-BshortcutHint=true",
                 "-Bruntime=" + System.getProperty("java.home"));
     }
 
--- a/modules/fxpackager/src/test/java/hello/TestPackager.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/fxpackager/src/test/java/hello/TestPackager.java	Thu Apr 24 10:37:43 2014 -0700
@@ -41,25 +41,28 @@
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.ListSelectionModel;
+import javax.swing.WindowConstants;
 
 public class TestPackager {
 
     private static void createAndShowGUI() {
         //Create and set up the window.
         try {
-            String preferencesId = System.getProperty("jvm.preferences.id");
+            String preferencesId = System.getProperty("app.preferences.id");
             Preferences node = Preferences.userRoot().node(preferencesId);
             Preferences jvmOptions = node.node("JVMUserOptions");
             String[] keys = jvmOptions.keys();
             for (String key: keys) {
                 System.out.println("key:" + key);
             }
+            jvmOptions.putLong("lastRunMs", System.currentTimeMillis());
+            node.flush();
         } catch (Exception ex) {
             Logger.getLogger(TestPackager.class.getName()).log(Level.WARNING, null, ex);
         }
 
         JFrame frame = new JFrame("Display Parameters");
-        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
 
         Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
         frame.setBounds(0, 0, dim.width / 4, dim.height / 4);
@@ -76,7 +79,7 @@
         RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
         List<String> arguments = RuntimemxBean.getInputArguments();
 
-        JList list = new JList(arguments.toArray(new String[arguments.size()]));
+        JList<String> list = new JList<>(arguments.toArray(new String[arguments.size()]));
         list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
         list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
         list.setVisibleRowCount(-1);
@@ -98,10 +101,6 @@
     public static void main(String[] args) {
         //Schedule a job for the event-dispatching thread:
         //creating and showing this application's GUI.
-        javax.swing.SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                createAndShowGUI();
-            }
-        });
+        javax.swing.SwingUtilities.invokeLater(TestPackager::createAndShowGUI);
     }
 }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacAccessible.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacAccessible.java	Thu Apr 24 10:37:43 2014 -0700
@@ -45,6 +45,7 @@
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyCodeCombination;
 import javafx.scene.input.KeyCombination;
+import javafx.scene.text.Font;
 import com.sun.glass.ui.PlatformAccessible;
 import com.sun.glass.ui.Screen;
 import com.sun.glass.ui.View;
@@ -78,6 +79,9 @@
         if (!_initEnum("MacOrientation")) {
             System.err.println("Fail linking MacOrientation");
         }
+        if (!_initEnum("MacText")) {
+            System.err.println("Fail linking MacText");
+        }
     }
 
     static enum MacAttribute {
@@ -162,6 +166,8 @@
         NSAccessibilityRangeForLineParameterizedAttribute(LINE_START, MacVariant::createNSValueForRange, MacVariant.NSNumber_Int),
         NSAccessibilityAttributedStringForRangeParameterizedAttribute(TITLE, MacVariant::createNSAttributedString, MacVariant.NSValue_range),
         NSAccessibilityCellForColumnAndRowParameterizedAttribute(CELL_AT_ROW_COLUMN, MacVariant::createNSObject, MacVariant.NSArray_int),
+        NSAccessibilityRangeForPositionParameterizedAttribute(OFFSET_AT_POINT, MacVariant::createNSValueForRange, MacVariant.NSValue_point),
+        NSAccessibilityBoundsForRangeParameterizedAttribute(BOUNDS_FOR_RANGE, MacVariant::createNSValueForRectangle, MacVariant.NSValue_range),
 
         ;long ptr; /* Initialized natively - treat as final */
         Attribute jfxAttr;
@@ -571,6 +577,20 @@
         ;long ptr; /* Initialized natively - treat as final */
     }
 
+    static enum MacText {
+        NSAccessibilityBackgroundColorTextAttribute,
+        NSAccessibilityForegroundColorTextAttribute,
+        NSAccessibilityUnderlineTextAttribute,
+        NSAccessibilityStrikethroughTextAttribute,
+        NSAccessibilityMarkedMisspelledTextAttribute,
+        NSAccessibilityFontTextAttribute,
+        NSAccessibilityFontNameKey,
+        NSAccessibilityFontFamilyKey,
+        NSAccessibilityVisibleNameKey,
+        NSAccessibilityFontSizeKey,
+        ;long ptr; /* Initialized natively - treat as final */
+    }
+
     /* Do not access the following lists directly from the Mac enums.
      * It can cause the static initialization to happen in an unexpected order.
      */
@@ -864,6 +884,17 @@
         return macRole;
     }
 
+    private Bounds flipBounds(Bounds bounds) {
+        View view = getRootView((Scene)getAttribute(SCENE));
+        if (view == null) return null;
+        Screen screen = view.getWindow().getScreen();
+        float height = screen.getHeight();
+        return new BoundingBox(bounds.getMinX(),
+                               height - bounds.getMinY() - bounds.getHeight(),
+                               bounds.getWidth(),
+                               bounds.getHeight());
+    }
+
     /* NSAccessibility Protocol - JNI entry points */
     long[] accessibilityAttributeNames() {
         if (getView() != null) return null; /* Let NSView answer for the Scene */
@@ -1246,16 +1277,7 @@
                  * NSAccessibilityPositionAttribute requires the point relative
                  * to the lower-left corner in screen.
                  */
-                View view = getRootView((Scene)getAttribute(SCENE));
-                if (view != null) {
-                    Screen screen = view.getWindow().getScreen();
-                    float height = screen.getHeight();
-                    Bounds bounds = (Bounds)result;
-                    result = new BoundingBox(bounds.getMinX(),
-                                             height - bounds.getMinY() - bounds.getHeight(),
-                                             bounds.getWidth(),
-                                             bounds.getHeight());
-                }
+                result = flipBounds((Bounds)result);
                 break;
             }
             case NSAccessibilityTitleAttribute: {
@@ -1525,10 +1547,11 @@
         Object value = variant.getValue();
         Object result;
         switch (attr) {
-            case NSAccessibilityCellForColumnAndRowParameterizedAttribute:
+            case NSAccessibilityCellForColumnAndRowParameterizedAttribute: {
                 int[] intArray = (int[])value;
                 result = getAttribute(attr.jfxAttr, intArray[1] /*row*/, intArray[0] /*column*/);
                 break;
+            }
             case NSAccessibilityLineForIndexParameterizedAttribute: {
                 if (getAttribute(ROLE) == Role.TEXT_AREA) {
                     result = getAttribute(attr.jfxAttr, value /*charOffset*/);
@@ -1554,12 +1577,72 @@
                 }
                 break;
             }
+            case NSAccessibilityBoundsForRangeParameterizedAttribute: {
+                int[] intArray = (int[])value; /* range.location, range.length */
+                Bounds[] bounds = (Bounds[])getAttribute(attr.jfxAttr, intArray[0], intArray[0] + intArray[1] - 1);
+                double left = Double.POSITIVE_INFINITY;
+                double top = Double.POSITIVE_INFINITY;
+                double right = Double.NEGATIVE_INFINITY;
+                double bottom = Double.NEGATIVE_INFINITY;
+                if (bounds != null) {
+                    for (int i = 0; i < bounds.length; i++) {
+                        Bounds b = bounds[i];
+                        if (b != null) {
+                            if (b.getMinX() < left) left = b.getMinX();
+                            if (b.getMinY() < top) top = b.getMinY();
+                            if (b.getMaxX() > right) right = b.getMaxX();
+                            if (b.getMaxY() > bottom) bottom = b.getMaxY();
+                        }
+                    }
+                }
+                result = flipBounds(new BoundingBox(left, top, right - left, bottom - top));
+                break;
+            }
+            case NSAccessibilityRangeForPositionParameterizedAttribute: {
+                float[] floatArray = (float[])value;
+                Integer offset = (Integer)getAttribute(attr.jfxAttr, new Point2D(floatArray[0], floatArray[1]));
+                if (offset != null) {
+                    result = new int[] {offset, 1};
+                } else {
+                    result = null;
+                }
+                break;
+            }
             default:
                 result = getAttribute(attr.jfxAttr, value);
         }
         if (result == null) return null;
         switch (attr) {
-            case NSAccessibilityAttributedStringForRangeParameterizedAttribute:
+            case NSAccessibilityAttributedStringForRangeParameterizedAttribute: {
+                String text = (String)result;
+                text = text.substring(variant.int1, variant.int1 + variant.int2);
+                List<MacVariant> styles = new ArrayList<>();
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    MacVariant fontDict = new MacVariant();
+                    fontDict.type = MacVariant.NSDictionary;
+                    fontDict.longArray = new long[] {
+                        MacText.NSAccessibilityFontNameKey.ptr,
+                        MacText.NSAccessibilityFontFamilyKey.ptr,
+                        MacText.NSAccessibilityVisibleNameKey.ptr,
+                        MacText.NSAccessibilityFontSizeKey.ptr,
+                    };
+                    fontDict.variantArray = new MacVariant[] {
+                        MacVariant.createNSString(font.getName()),
+                        MacVariant.createNSString(font.getFamily()),
+                        MacVariant.createNSString(font.getName()),
+                        MacVariant.createNSNumberForDouble(font.getSize()),
+                    };
+
+                    fontDict.key = MacText.NSAccessibilityFontTextAttribute.ptr;
+                    fontDict.location = 0;
+                    fontDict.length = text.length();
+                    styles.add(fontDict);
+                }
+                MacVariant attrString = attr.map.apply(text);
+                attrString.variantArray = styles.toArray(new MacVariant[0]);
+                return attrString;
+            }
             case NSAccessibilityStringForRangeParameterizedAttribute: {
                 String text = (String)result;
                 result = text.substring(variant.int1, variant.int1 + variant.int2);
--- a/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacVariant.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacVariant.java	Thu Apr 24 10:37:43 2014 -0700
@@ -33,36 +33,44 @@
 class MacVariant {
     final static int NSArray_id = 1;
     final static int NSArray_NSString = 2;
-    final static int NSArray_int = 18;
-    final static int NSArray_range = 19;
-    final static int NSAttributedString = 3;
-    final static int NSData = 4;
-    final static int NSDate = 5;
-    final static int NSDictionary = 6;
-    final static int NSNumber_Boolean = 7;
-    final static int NSNumber_Int = 8;
-    final static int NSNumber_Float = 9;
-    final static int NSNumber_Double = 10;
-    final static int NSString = 11;
-    final static int NSURL = 12;
-    final static int NSValue_point = 13;
-    final static int NSValue_size = 14;
-    final static int NSValue_rectangle = 15;
-    final static int NSValue_range = 15;
-    final static int NSObject = 17; /* id */
+    final static int NSArray_int = 3;
+    final static int NSArray_range = 4;
+    final static int NSAttributedString = 5; /* Uses string for the text and variantArray for the styles */
+    final static int NSData = 6;
+    final static int NSDate = 7;
+    final static int NSDictionary = 8; /* Uses longArray for keys (NSString) and variantArray for values */
+    final static int NSNumber_Boolean = 9;
+    final static int NSNumber_Int = 10;
+    final static int NSNumber_Float = 11;
+    final static int NSNumber_Double = 12;
+    final static int NSString = 13;
+    final static int NSURL = 14;
+    final static int NSValue_point = 15;
+    final static int NSValue_size = 16;
+    final static int NSValue_rectangle = 17;
+    final static int NSValue_range = 18;
+    final static int NSObject = 19; /* id */
 
     int type;
     long[] longArray;
     int[] intArray;
     String[] stringArray;
+    MacVariant[] variantArray; /* Used by NSAttributedString and NSDictionary */
     float float1;
     float float2;
+    float float3;
+    float float4;
     int int1;
     int int2;
     String string;
     long long1;
     double double1;
 
+    /* Used when the Variant represents an attribute within a NSAttributedString */
+    int location;
+    int length;
+    long key;
+
     static MacVariant createNSArray(Object result) {
         MacVariant variant = new MacVariant();
         variant.type = NSArray_id;
@@ -119,6 +127,17 @@
         return variant;
     }
 
+    static MacVariant createNSValueForRectangle(Object result) {
+        Bounds bounds = (Bounds)result;
+        MacVariant variant = new MacVariant();
+        variant.type = NSValue_rectangle;
+        variant.float1 = (float)bounds.getMinX();
+        variant.float2 = (float)bounds.getMinY();
+        variant.float3 = (float)bounds.getWidth();
+        variant.float4 = (float)bounds.getHeight();
+        return variant;
+    }
+
     static MacVariant createNSValueForRange(Object result) {
         int[] range = (int[])result;
         MacVariant variant = new MacVariant();
@@ -158,6 +177,11 @@
             case NSArray_id: return longArray;
             case NSArray_int: return intArray;
             case NSValue_range: return new int[] {int1, int2};
+            case NSValue_point: return new float[] {float1, float2};
+            case NSValue_size: return new float[] {float1, float2};
+            case NSValue_rectangle: return new float[] {float1, float2, float3, float4};
+            case NSString: return string;
+            case NSAttributedString: return string;
             //TODO REST
         }
         return null;
@@ -170,6 +194,8 @@
             case NSArray_id: v = Arrays.toString((long[])v); break;
             case NSArray_int: v = Arrays.toString((int[])v); break;
             case NSValue_range: v = Arrays.toString((int[])v); break;
+            case NSAttributedString: v += Arrays.toString(variantArray); break;
+            case NSDictionary: v = "keys: " + Arrays.toString(longArray) + " values: " + Arrays.toString(variantArray);
         }
         return "MacVariant type: " + type + " value " + v;
     }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxMouseProcessor.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxMouseProcessor.java	Thu Apr 24 10:37:43 2014 -0700
@@ -34,14 +34,18 @@
     private MouseInput mouse = MouseInput.getInstance();
     private MouseState previousState = new MouseState();
     private MouseState state = new MouseState();
-    private boolean processedFirstEvent;
+    /**
+     * does previousState hold an update that has not yet been sent to
+     * MouseInput?
+     */
+    private boolean hasPendingState;
 
     @Override
     public void processEvents(LinuxInputDevice device) {
         LinuxEventBuffer buffer = device.getBuffer();
         mouse.getState(previousState);
         mouse.getState(state);
-        processedFirstEvent = false;
+        hasPendingState = false;
         while (buffer.hasNextEvent()) {
             switch (buffer.getEventType()) {
                 case Input.EV_REL:
@@ -95,26 +99,24 @@
             }
             buffer.nextEvent();
         }
-        mouse.setState(previousState, false);
+        if (hasPendingState) {
+            mouse.setState(previousState, false);
+        }
     }
 
     private void sendEvent() {
-        if (!processedFirstEvent) {
-            mouse.getState(previousState);
-            if (state.canBeFoldedWith(previousState)) {
-                processedFirstEvent = true;
-            } else {
-                mouse.setState(state, false);
+        if (state.canBeFoldedWith(previousState)) {
+            // fold together MouseStates that differ only in their coordinates
+            hasPendingState = true;
+        } else {
+            // the events are different.
+            if (hasPendingState) {
+                // send and clear the pending state
+                mouse.setState(previousState, false);
+                hasPendingState = false;
             }
-        }
-        if (processedFirstEvent) {
-            // fold together MouseStates that differ only in their coordinates
-            if (!state.canBeFoldedWith(previousState)) {
-                // the events are different. Send "previousState".
-                mouse.setState(previousState, false);
-            }
-        } else {
-            processedFirstEvent = true;
+            // send this event
+            mouse.setState(state, false);
         }
         state.copyTo(previousState);
     }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxSimpleTouchProcessor.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxSimpleTouchProcessor.java	Thu Apr 24 10:37:43 2014 -0700
@@ -71,7 +71,7 @@
                         case Input.BTN_TOUCH:
                             if (buffer.getEventValue() == 0) {
                                 touchReleased = true;
-                            } else {
+                            } else if (state.getPointCount() == 0) {
                                 // restore an old point
                                 state.addPoint(null);
                             }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/win/WinAccessible.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/win/WinAccessible.java	Thu Apr 24 10:37:43 2014 -0700
@@ -123,6 +123,7 @@
     private static final int UIA_EditControlTypeId               = 50004;
     private static final int UIA_HyperlinkControlTypeId          = 50005;
     private static final int UIA_ImageControlTypeId              = 50006;
+    private static final int UIA_ListItemControlTypeId           = 50007;
     private static final int UIA_ListControlTypeId               = 50008;
     private static final int UIA_MenuControlTypeId               = 50009;
     private static final int UIA_MenuBarControlTypeId            = 50010;
@@ -419,6 +420,12 @@
         return peer;
     }
 
+    /* Overwritten in order to make is visible to WinTextRangeProvider */
+    @Override
+    protected Object getAttribute(Attribute attribute, Object... parameters) {
+        return super.getAttribute(attribute, parameters);
+    }
+
     private long getContainer(Role targetRole) {
         Node node = getContainerNode(targetRole);
         return node == null ? 0 : getAccessible(node);
@@ -467,9 +474,9 @@
             case TEXT_AREA: return UIA_TextControlTypeId;
             case TABLE_VIEW: return UIA_TableControlTypeId;
             case LIST_VIEW: return UIA_ListControlTypeId;
+            case LIST_ITEM: return UIA_ListItemControlTypeId;
             case TREE_TABLE_CELL:
-            case TABLE_CELL:
-            case LIST_ITEM: return UIA_DataItemControlTypeId;
+            case TABLE_CELL: return UIA_DataItemControlTypeId;
             case IMAGE: return UIA_ImageControlTypeId;
             case RADIO_BUTTON: return UIA_RadioButtonControlTypeId;
             case CHECKBOX: return UIA_CheckBoxControlTypeId;
@@ -1053,17 +1060,17 @@
 
     boolean get_CanSelectMultiple() {
         if (isDisposed()) return false;
-
         Role role = (Role)getAttribute(ROLE);
-        switch (role) {
-            case LIST_VIEW:
-            case TABLE_VIEW:
-            case TREE_VIEW:
-            case TREE_TABLE_VIEW:
-                return (boolean)getAttribute(MULTIPLE_SELECTION);
-            default:
+        if (role != null) {
+            switch (role) {
+                case LIST_VIEW:
+                case TABLE_VIEW:
+                case TREE_VIEW:
+                case TREE_TABLE_VIEW:
+                    return Boolean.TRUE.equals(getAttribute(MULTIPLE_SELECTION));
+                default:
+            }
         }
-
         return false;
     }
 
@@ -1214,7 +1221,13 @@
 
     long RangeFromPoint(double x, double y) {
         if (isDisposed()) return 0;
-        return get_DocumentRange();
+        Integer offset = (Integer)getAttribute(OFFSET_AT_POINT, new Point2D(x, y));
+        if (offset != null) {
+            WinTextRangeProvider range = new WinTextRangeProvider(this);
+            range.setRange(offset, offset);
+            return range.getNativeProvider();
+        }
+        return 0;
     }
 
     long get_DocumentRange() {
--- a/modules/graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/win/WinTextRangeProvider.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,6 +25,12 @@
 
 package com.sun.glass.ui.win;
 
+import static javafx.scene.accessibility.Attribute.*;
+import javafx.geometry.Bounds;
+import javafx.scene.accessibility.Attribute;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+
 /*
  * This class is the Java peer for GlassTextRangeProvider.
  * GlassTextRangeProvider implements ITextRangeProvider.
@@ -49,6 +55,14 @@
     private static final int TextUnit_Page = 5;
     private static final int TextUnit_Document = 6;
 
+    /* Text Attribute Identifiers */
+    private static final int UIA_FontNameAttributeId = 40005;
+    private static final int UIA_FontSizeAttributeId = 40006;
+    private static final int UIA_FontWeightAttributeId = 40007;
+    private static final int UIA_IsHiddenAttributeId = 40013;
+    private static final int UIA_IsItalicAttributeId = 40014;
+    private static final int UIA_IsReadOnlyAttributeId = 40015;
+
     private static int idCount = 1;
     private int id;
     private int start, end;
@@ -84,13 +98,16 @@
         return "Range(start: "+start+", end: "+end+", id: " + id + ")";
     }
 
+    private Object getAttribute(Attribute attribute, Object... parameters) {
+        return accessible.getAttribute(attribute, parameters);
+    }
+
     /***********************************************/
     /*            ITextRangeProvider               */
     /***********************************************/
     long Clone() {
         WinTextRangeProvider clone = new WinTextRangeProvider(accessible);
         clone.setRange(start, end);
-        System.out.println("Cloning " + id + " to " + clone.id);
 
         /* Note: Currently Clone() natively does not call AddRef() no the returned object.
          * This mean we don't keep a reference of our own and we don't 
@@ -101,20 +118,54 @@
     }
 
     boolean Compare(WinTextRangeProvider range) {
-        System.out.println("Compare " + this + " to " + range);
+        System.out.println("+Compare " + this + " to " + range);
         if (range == null) return false;
         return accessible == range.accessible && start == range.start && end == range.end;
     }
 
     int CompareEndpoints(int endpoint, WinTextRangeProvider targetRange, int targetEndpoint) {
-        System.out.println("CompareEndpoints " + endpoint + " " + this + " " + targetRange + " " + targetEndpoint);
+        System.out.println("+CompareEndpoints " + endpoint + " " + this + " " + targetRange + " " + targetEndpoint);
         int offset = endpoint == TextPatternRangeEndpoint_Start ? start : end;
         int targetOffset = targetEndpoint == TextPatternRangeEndpoint_Start ? targetRange.start : targetRange.end;
         return targetOffset - offset;
     }
 
     void ExpandToEnclosingUnit(int unit) {
-        System.out.println("ExpandToEnclosingUnit " + this + " unit " + unit);
+        switch (unit) {
+            case TextUnit_Character: {
+                Integer caretOffset = (Integer)getAttribute(CARET_OFFSET);
+                if (caretOffset == null) return;
+                start = end = caretOffset;
+                break;
+            }
+            case TextUnit_Format:
+            case TextUnit_Word:
+                //TODO
+                break;
+            case TextUnit_Line:
+            case TextUnit_Paragraph: {
+                Integer caretOffset = (Integer)getAttribute(CARET_OFFSET);
+                if (caretOffset == null) return;
+                Integer lineIndex = (Integer)getAttribute(LINE_FOR_OFFSET, caretOffset);
+                if (lineIndex == null) return;
+                Integer lineStart = (Integer)getAttribute(LINE_START, lineIndex);
+                if (lineStart == null) return;
+                Integer lineEnd = (Integer)getAttribute(LINE_START, lineIndex);
+                if (lineEnd == null) return;
+                start = lineStart;
+                end = lineEnd;
+                break;
+            }
+            case TextUnit_Document:
+            case TextUnit_Page: {
+                String text = (String)getAttribute(TITLE);
+                if (text == null) return;
+                start = 0;
+                end = text.length();
+                break;
+            }
+        }
+        System.out.println("+ExpandToEnclosingUnit " + this + " unit " + unit);
     }
 
     long FindAttribute(int attributeId, WinVariant val, boolean backward) {
@@ -128,28 +179,120 @@
     }
 
     WinVariant GetAttributeValue(int attributeId) {
-        System.out.println("GetAttributeValue");
-        return null;
+//        System.out.println("+GetAttributeValue " + attributeId);
+        WinVariant variant = null;
+        switch (attributeId) {
+            case UIA_FontNameAttributeId: {
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    variant = new WinVariant();
+                    variant.vt = WinVariant.VT_BSTR;
+                    variant.bstrVal = font.getName();
+                }
+                break;
+            }
+            case UIA_FontSizeAttributeId: {
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    variant = new WinVariant();
+                    variant.vt = WinVariant.VT_R8;
+                    variant.dblVal = font.getSize();
+                }
+                break;
+            }
+            case UIA_FontWeightAttributeId: {
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    boolean bold = font.getStyle().toLowerCase().contains("bold");
+                    variant = new WinVariant();
+                    variant.vt = WinVariant.VT_I4;
+                    variant.lVal = bold ? FontWeight.BOLD.getWeight() : FontWeight.NORMAL.getWeight();
+                }
+                break;
+            }
+            case UIA_IsHiddenAttributeId:
+            case UIA_IsReadOnlyAttributeId:
+                variant = new WinVariant();
+                variant.vt = WinVariant.VT_BOOL;
+                variant.boolVal = false;
+                break;
+            case UIA_IsItalicAttributeId: {
+                Font font = (Font)getAttribute(FONT);
+                if (font != null) {
+                    boolean italic = font.getStyle().toLowerCase().contains("italic");
+                    variant = new WinVariant();
+                    variant.vt = WinVariant.VT_BOOL;
+                    variant.boolVal = italic;   
+                }
+                break;
+            }
+            default:
+//                System.out.println("GetAttributeValue " + attributeId + " Not implemented");
+        }
+        return variant;
     }
 
     double[] GetBoundingRectangles() {
-        System.out.println("GetBoundingRectangles");
+        Bounds[] bounds = (Bounds[])getAttribute(BOUNDS_FOR_RANGE, start, end);
+        if (bounds != null) {
+            double[] result = new double[bounds.length * 4];
+            int index = 0;
+            for (int i = 0; i < bounds.length; i++) {
+                Bounds b = bounds[i];
+                result[index++] = b.getMinX();
+                result[index++] = b.getMinY();
+                result[index++] = b.getWidth();
+                result[index++] = b.getHeight();
+            }
+            return result;
+        }
         return null;
     }
 
     long GetEnclosingElement() {
-        System.out.println("GetEnclosingElement");
-        return 0;
+        return accessible.getNativeAccessible();
     }
 
     String GetText(int maxLength) {
-        System.out.println("GetText");
-        return null;
+        String text = (String)getAttribute(TITLE);
+        if (text == null) return null;
+        int endOffset = maxLength != -1 ? Math.min(end, start + maxLength) : end;
+        System.out.println("+GetText [" + text.substring(start, endOffset)+"]");
+        return text.substring(start, endOffset);
     }
 
     int Move(int unit, int count) {
-        System.out.println("Move");
-        return 0;
+        System.out.println("+Move " + unit + " " + count + " " + this);
+
+        int offset = start;
+        switch (unit) {
+            case TextUnit_Character: {
+                start = offset + count; //check range
+                end = start + 1;
+                break;
+            }
+            case TextUnit_Format:
+            case TextUnit_Word:
+                //TODO
+                break;
+            case TextUnit_Line:
+            case TextUnit_Paragraph: {
+                Integer lineIndex = (Integer)getAttribute(LINE_FOR_OFFSET, offset);
+                lineIndex += count;//check range;
+                Integer lineStart = (Integer)getAttribute(LINE_START, lineIndex);
+                if (lineStart == null) return 0;
+                Integer lineEnd = (Integer)getAttribute(LINE_START, lineIndex);
+                if (lineEnd == null) return 0;
+                start = lineStart;
+                end = lineEnd;
+                break;
+            }
+            case TextUnit_Document:
+            case TextUnit_Page: {
+               return 0;
+            }
+        }
+        return count;
     }
 
     int MoveEndpointByUnit(int endpoint, int unit, int count) {
@@ -158,7 +301,16 @@
     }
 
     void MoveEndpointByRange(int endpoint, WinTextRangeProvider targetRange, int targetEndpoint) {
-        System.out.println("MoveEndpointByRange");
+        int offset = targetEndpoint == TextPatternRangeEndpoint_Start ? targetRange.start : targetRange.end;
+        if (endpoint == TextPatternRangeEndpoint_Start) {
+            start = offset;
+        } else {
+            end = offset;
+        }
+        if (start > end) {
+            start = end = offset;
+        }
+        System.out.println("+MoveEndpointByRange");
     }
 
     void Select() {
@@ -178,8 +330,7 @@
     }
 
     long[] GetChildren() {
-        System.out.println("GetChildren");
-        return null;
+        return new long[0];
     }
 
 }
--- a/modules/graphics/src/main/java/javafx/scene/accessibility/Attribute.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/javafx/scene/accessibility/Attribute.java	Thu Apr 24 10:37:43 2014 -0700
@@ -274,14 +274,14 @@
     /**
      * Returns the Node at the given point location.
      * Type: Node
-     * Parameters: Point
+     * Parameters: Point2D
      */
     NODE_AT_POINT("NodeAtPoint", Node.class),
 
     /**
      * Returns the char offset at the given point location.
      * Type: Integer
-     * Parameters: Point
+     * Parameters: Point2D
      */
     OFFSET_AT_POINT("OffsetAtPoint", Integer.class),
 
--- a/modules/graphics/src/main/java/javafx/scene/text/Text.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/java/javafx/scene/text/Text.java	Thu Apr 24 10:37:43 2014 -0700
@@ -50,6 +50,8 @@
 import javafx.scene.accessibility.Role;
 import javafx.scene.paint.Color;
 import javafx.scene.paint.Paint;
+import javafx.scene.shape.LineTo;
+import javafx.scene.shape.MoveTo;
 import javafx.scene.shape.PathElement;
 import javafx.scene.shape.Shape;
 import javafx.scene.shape.StrokeType;
@@ -1939,6 +1941,32 @@
                 }
                 return 0;
             }
+            case OFFSET_AT_POINT: {
+                Point2D point = (Point2D)parameters[0];
+                point = screenToLocal(point);
+                return impl_hitTestChar(point).getCharIndex();
+            }
+            case BOUNDS_FOR_RANGE: {
+                int start = (Integer)parameters[0];
+                int end = (Integer)parameters[1];
+                PathElement[] elements = impl_getRangeShape(start, end + 1);
+                /* Each bounds is defined by a MoveTo (top-left) followed by 
+                 * 4 LineTo (to top-right, bottom-right, bottom-left, back to top-left).
+                 */
+                Bounds[] bounds = new Bounds[elements.length / 5];
+                int index = 0;
+                for (int i = 0; i < bounds.length; i++) {
+                    MoveTo topLeft = (MoveTo)elements[index];
+                    LineTo topRight = (LineTo)elements[index+1];
+                    LineTo bottomRight = (LineTo)elements[index+2];
+                    BoundingBox b = new BoundingBox(topLeft.getX(), topLeft.getY(), 
+                                                    topRight.getX() - topLeft.getX(),
+                                                    bottomRight.getY() - topRight.getY());
+                    bounds[i] = localToScreen(b);
+                    index += 5;
+                }
+                return bounds;
+            }
             default: return super.accGetAttribute(attribute, parameters);
         }
     }
--- a/modules/graphics/src/main/native-glass/gtk/glass_dnd.cpp	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/gtk/glass_dnd.cpp	Thu Apr 24 10:37:43 2014 -0700
@@ -84,7 +84,7 @@
     TARGET_MIME_JPEG_ATOM = gdk_atom_intern_static_string("image/jpeg");
     TARGET_MIME_TIFF_ATOM = gdk_atom_intern_static_string("image/tiff");
     TARGET_MIME_BMP_ATOM = gdk_atom_intern_static_string("image/bmp");
-    
+
     target_atoms_initialized = TRUE;
 }
 
@@ -563,6 +563,7 @@
 
         gdk_window_destroy(dnd_window);
         dnd_window = NULL;
+        DragView::reset_drag_view();
     }
     
     return FALSE;
@@ -815,12 +816,14 @@
 
 static void process_drag_motion(gint x_root, gint y_root, guint state)
 {
+    DragView::move(x_root, y_root);
+
     GdkWindow *dest_window;
     GdkDragProtocol prot;
 
     gdk_drag_find_window_for_screen(get_drag_context(), NULL, gdk_screen_get_default(),
             x_root, y_root, &dest_window, &prot);
-    
+
     if (prot != GDK_DRAG_PROTO_NONE) {
         GdkDragAction action, possible_actions;
         determine_actions(state, &action, &possible_actions);
@@ -1002,7 +1005,9 @@
     
     g_object_set_data_full(G_OBJECT(src_window), SOURCE_DND_DATA, data, clear_global_ref);
     g_object_set_data(G_OBJECT(src_window), SOURCE_DND_ACTIONS, (gpointer)translate_glass_action_to_gdk(supported));
-    
+
+    DragView::set_drag_view();
+
     ctx = gdk_drag_begin(src_window, targets);
     
     g_list_free(targets);
@@ -1028,3 +1033,238 @@
     return dnd_get_performed_action();
 }
 
+ /******************** DRAG VIEW ***************************/
+DragView::View* DragView::view = NULL;
+
+void DragView::reset_drag_view() {
+    delete view;
+    view = NULL;
+}
+
+gboolean DragView::get_drag_image_offset(int* x, int* y) {
+    gboolean offset_set = FALSE;
+    jobject bb = dnd_source_get_data("application/x-java-drag-image-offset");
+    if (bb) {
+        jbyteArray byteArray = (jbyteArray)mainEnv->CallObjectMethod(bb, jByteBufferArray);
+        if (!EXCEPTION_OCCURED(mainEnv)) {
+            jbyte* raw = mainEnv->GetByteArrayElements(byteArray, NULL);
+            jsize nraw = mainEnv->GetArrayLength(byteArray);
+
+            if ((size_t) nraw >= sizeof(jint) * 2) {
+                jint* r = (jint*) raw;
+                *x = BSWAP_32(r[0]);
+                *y = BSWAP_32(r[1]);
+                offset_set = TRUE;
+            }
+
+            mainEnv->ReleaseByteArrayElements(byteArray, raw, JNI_ABORT);
+        }
+    }
+    return offset_set;
+}
+
+GdkPixbuf* DragView::get_drag_image(gboolean* is_raw_image, gint* width, gint* height) {
+    GdkPixbuf *pixbuf = NULL;
+    gboolean is_raw = FALSE;
+
+    jobject drag_image = dnd_source_get_data("application/x-java-drag-image");
+
+    if (drag_image) {
+        jbyteArray byteArray = (jbyteArray) mainEnv->CallObjectMethod(drag_image, jByteBufferArray);
+        if (!EXCEPTION_OCCURED(mainEnv)) {
+
+            jbyte* raw = mainEnv->GetByteArrayElements(byteArray, NULL);
+            jsize nraw = mainEnv->GetArrayLength(byteArray);
+
+            int w = 0, h = 0;
+            int whsz = sizeof(jint) * 2; // Pixels are stored right after two ints
+                                         // in this byteArray: width and height
+            if (nraw > whsz) {
+                jint* int_raw = (jint*) raw;
+                w = BSWAP_32(int_raw[0]);
+                h = BSWAP_32(int_raw[1]);
+
+                // We should have enough pixels for requested width and height
+                if ((nraw - whsz) / 4 - w * h >= 0 ) {
+                    guchar* data = (guchar*) g_try_malloc0(nraw - whsz);
+                    if (data) {
+                        memcpy(data, (raw + whsz), nraw - whsz);
+                        pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8,
+                                w, h, w * 4, (GdkPixbufDestroyNotify) g_free, NULL);
+                    }
+                }
+            }
+            mainEnv->ReleaseByteArrayElements(byteArray, raw, JNI_ABORT);
+        }
+    }
+
+    if (!GDK_IS_PIXBUF(pixbuf)) {
+        jobject pixels = dnd_source_get_data("application/x-java-rawimage");
+        if (pixels) {
+            is_raw = TRUE;
+            mainEnv->CallVoidMethod(pixels, jPixelsAttachData, PTR_TO_JLONG(&pixbuf));
+            CHECK_JNI_EXCEPTION_RET(mainEnv, NULL)
+        }
+    }
+
+    if (!GDK_IS_PIXBUF(pixbuf)) {
+        return NULL;
+    }
+
+    int w = gdk_pixbuf_get_width(pixbuf);
+    int h = gdk_pixbuf_get_height(pixbuf);
+
+    if (w > DRAG_IMAGE_MAX_WIDTH || h > DRAG_IMAGE_MAX_HEIGH) {
+        double rw = DRAG_IMAGE_MAX_WIDTH / (double)w;
+        double rh =  DRAG_IMAGE_MAX_HEIGH / (double)h;
+        double r = MIN(rw, rh);
+
+
+        int new_w = w * r;
+        int new_h = h * r;
+
+        w = new_w;
+        h = new_h;
+
+        GdkPixbuf *tmp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, new_w, new_h, GDK_INTERP_TILES);
+        g_object_unref(pixbuf);
+        if (!GDK_IS_PIXBUF(tmp_pixbuf)) {
+            return NULL;
+        }
+        pixbuf = tmp_pixbuf;
+    }
+
+    *is_raw_image = is_raw;
+    *width = w;
+    *height = h;
+
+    return pixbuf;
+}
+
+void DragView::set_drag_view() {
+    reset_drag_view();
+
+    gboolean is_raw_image = FALSE;
+    gint w = 0, h = 0;
+    GdkPixbuf* pixbuf = get_drag_image(&is_raw_image, &w, &h);
+
+    if (GDK_IS_PIXBUF(pixbuf)) {
+        gint offset_x = w / 2;
+        gint offset_y = h / 2;
+
+        gboolean is_offset_set = get_drag_image_offset(&offset_x, &offset_y);
+
+        DragView::view = new DragView::View(pixbuf, is_raw_image, is_offset_set, offset_x, offset_y);
+    }
+}
+void DragView::move(gint x, gint y) {
+    if (view) {
+        view->move(x, y);
+    }
+}
+
+static void on_screen_changed(GtkWidget *widget, GdkScreen *previous_screen, gpointer view) {
+    ((DragView::View*) view)->screen_changed();
+}
+
+static gboolean on_expose(GtkWidget *widget, GdkEventExpose *event, gpointer view) {
+    ((DragView::View*) view)->expose();
+    return FALSE;
+}
+
+DragView::View::View(GdkPixbuf* _pixbuf, gboolean _is_raw_image,
+                                gboolean _is_offset_set, gint _offset_x, gint _offset_y) :
+        pixbuf(_pixbuf),
+        is_raw_image(_is_raw_image),
+        is_offset_set(_is_offset_set),
+        offset_x(_offset_x),
+        offset_y(_offset_y)
+{
+    width = gdk_pixbuf_get_width(pixbuf);
+    height = gdk_pixbuf_get_height(pixbuf);
+
+    widget = gtk_window_new(GTK_WINDOW_POPUP);
+    gtk_window_set_type_hint(GTK_WINDOW(widget), GDK_WINDOW_TYPE_HINT_DND);
+
+    screen_changed();
+
+    gtk_widget_realize(widget);
+
+    GdkRegion* region = gdk_region_new();
+    gdk_window_input_shape_combine_region(gtk_widget_get_window(widget), region, 0,0);
+    gdk_region_destroy(region);
+
+    gtk_widget_set_app_paintable(widget, TRUE);
+
+    g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(on_expose), this);
+    g_signal_connect(G_OBJECT(widget), "screen-changed", G_CALLBACK(on_screen_changed), this);
+
+    gtk_widget_set_size_request(widget, width, height);
+
+    gtk_window_set_decorated(GTK_WINDOW(widget), FALSE);
+    gtk_window_move(GTK_WINDOW(widget), -10000, -10000);
+    gtk_window_set_opacity(GTK_WINDOW(widget), .7);
+    gtk_widget_show_all(widget);
+}
+
+void DragView::View::screen_changed() {
+    GdkScreen *screen = gtk_widget_get_screen(widget);
+    GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
+
+    if (!colormap || !gdk_screen_is_composited(screen)) {
+        if (!is_offset_set) {
+            offset_x = 1;
+            offset_y = 1;
+        }
+    }
+
+    if (!colormap) {
+        colormap = gdk_screen_get_rgb_colormap(screen);
+    }
+    gtk_widget_set_colormap(widget, colormap);
+}
+
+void DragView::View::expose() {
+    cairo_t *context = gdk_cairo_create(widget->window);
+
+    cairo_surface_t* cairo_surface;
+
+    guchar* pixels = is_raw_image
+            ? (guchar*) convert_BGRA_to_RGBA((const int*) gdk_pixbuf_get_pixels(pixbuf),
+                                                gdk_pixbuf_get_rowstride(pixbuf),
+                                                height)
+            : gdk_pixbuf_get_pixels(pixbuf);
+
+    cairo_surface = cairo_image_surface_create_for_data(
+            pixels,
+            CAIRO_FORMAT_ARGB32,
+            width, height, width * 4);
+
+    cairo_set_source_surface(context, cairo_surface, 0, 0);
+    cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(context);
+
+    if (is_raw_image) {
+        g_free(pixels);
+    }
+    cairo_destroy(context);
+    cairo_surface_destroy(cairo_surface);
+}
+
+void DragView::View::move(gint x, gint y) {
+    if (!gtk_events_pending()) { // avoid sluggish window move
+        gtk_window_move(GTK_WINDOW(widget), x - offset_x, y - offset_y);
+    }
+}
+
+DragView::View::~View() {
+    if (widget) {
+        gtk_widget_destroy(widget);
+        widget == NULL;
+    }
+    if (pixbuf) {
+        g_object_unref(pixbuf);
+        pixbuf == NULL;
+    }
+}
+
--- a/modules/graphics/src/main/native-glass/gtk/glass_dnd.h	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/gtk/glass_dnd.h	Thu Apr 24 10:37:43 2014 -0700
@@ -41,5 +41,47 @@
 
 gboolean is_in_drag();
 
+#define DRAG_IMAGE_MAX_WIDTH 320
+#define DRAG_IMAGE_MAX_HEIGH 240
+
+#define BSWAP_32(x) (((int)(x) << 24)  | \
+          (((int)(x) << 8) & 0xff0000) | \
+          (((int)(x) >> 8) & 0xff00)   | \
+          ((int)(x)  >> 24))
+
+class DragView {
+public:
+    class View {
+        GtkWidget* widget;
+        GdkPixbuf* pixbuf;
+        gint width, height;
+        gboolean is_raw_image;
+        gboolean is_offset_set;
+        gint offset_x, offset_y;
+    public:
+        View(GdkPixbuf* pixbuf, gboolean is_raw_image, gboolean is_offset_set, gint offset_x, gint offset_y);
+        void screen_changed();
+        void expose();
+        void move(gint x, gint y);
+        ~View();
+    private:
+        View(View&);
+        View& operator=(const View&);
+    };
+
+    static void reset_drag_view();
+    static void set_drag_view();
+    static void move(gint x, gint y);
+
+private:
+    static View* view;
+    static gboolean get_drag_image_offset(int* x, int* y);
+    static GdkPixbuf* get_drag_image(gboolean* is_raw_image, gint* width, gint* height);
+
+    DragView() {}
+    DragView(DragView&);
+    DragView& operator=(const DragView&);
+};
+
 #endif        /* GLASS_DND_H */
 
--- a/modules/graphics/src/main/native-glass/mac/GlassAccessible.h	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassAccessible.h	Thu Apr 24 10:37:43 2014 -0700
@@ -34,11 +34,17 @@
 - (jobject)getJAccessible;
 @end
 
-id (^jLongToID)(void*, CFIndex);
-id (^jIntToNSNumber)(void*, CFIndex);
+/* The following blocks are used by jArrayToNSArray() to convert java types
+ * within a java array to a native type to be stored in the resulting NSArray.
+ */
+typedef id (^jMapper)(void*, CFIndex);
+jMapper jLongToID;
+jMapper jIntToNSNumber;
+jMapper jVariantToID;
+
 id variantToID(JNIEnv *env, jobject variant);
 NSString* jStringToNSString(JNIEnv *env, jstring string);
-NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, id (^)(void*, CFIndex));
+NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, jMapper);
 
 /* Accessible class IDs for classes, methods, and fields (this could be in GlassStatics.h) */
 
@@ -72,6 +78,12 @@
 jfieldID jVariantLong1;
 jfieldID jVariantFloat1;
 jfieldID jVariantFloat2;
+jfieldID jVariantFloat3;
+jfieldID jVariantFloat4;
 jfieldID jVariantDouble1;
 jfieldID jVariantString;
+jfieldID jVariantVariantArray;
+jfieldID jVariantLocation;
+jfieldID jVariantLength;
+jfieldID jVariantKey;
 
--- a/modules/graphics/src/main/native-glass/mac/GlassAccessible.m	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassAccessible.m	Thu Apr 24 10:37:43 2014 -0700
@@ -122,7 +122,6 @@
     return jresult;
 }
 
-
 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount
 {
     jlongArray jresult = NULL;
@@ -225,7 +224,7 @@
 
 @end
 
-NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, id (^mapper)(void*, CFIndex)) {
+NSArray* jArrayToNSArray(JNIEnv *env, jarray srcArray, jMapper mapper) {
     if (srcArray == NULL) return NULL;
     jsize size = (*env)->GetArrayLength(env, srcArray);
 
@@ -233,17 +232,27 @@
     NSMutableArray *array = [NSMutableArray arrayWithCapacity: size];
     if (size <= 0) return array;
 
+    /* Do not use GetPrimitiveArrayCritical, variantToID() can be used recursively */
+    if (mapper == jVariantToID) {
+        for (CFIndex index = 0; index < size; index++) {
+            jobject element = (*env)->GetObjectArrayElement(env, srcArray, index);
+            if ((*env)->ExceptionCheck(env)) return NULL;
+            [array addObject: variantToID(env, element)];
+        }
+        return array;
+    }
+
     void* ptr = (*env)->GetPrimitiveArrayCritical(env, srcArray, 0);
     if (ptr) {
-	    @try {
-	        for (CFIndex index = 0; index < size; index++) {
-	            [array addObject: mapper(ptr, index)];
-	        }
-	    }
-	    @finally {
-	        (*env)->ReleasePrimitiveArrayCritical(env, srcArray, ptr, 0);
-	    }
-	}
+        @try {
+            for (CFIndex index = 0; index < size; index++) {
+                [array addObject: mapper(ptr, index)];
+            }
+        }
+        @finally {
+            (*env)->ReleasePrimitiveArrayCritical(env, srcArray, ptr, 0);
+        }
+    }
     return array;
 }
 
@@ -253,13 +262,13 @@
     NSString *result = NULL;
     const jchar *chars =(*env)->GetStringCritical(env, string, 0);
     if (chars) {
-	    @try {
-	        result = [NSString stringWithCharacters: chars length: length];
-	    }
-	    @finally {
-	        (*env)->ReleaseStringCritical(env, string, chars);
-	    }
-	}
+        @try {
+            result = [NSString stringWithCharacters: chars length: length];
+        }
+        @finally {
+            (*env)->ReleaseStringCritical(env, string, chars);
+        }
+    }
     return result;
 }
 
@@ -282,11 +291,41 @@
         jstring string = (*env)->GetObjectField(env, variant, jVariantString);
         return jStringToNSString(env, string);
     }
+    case com_sun_glass_ui_mac_MacVariant_NSDictionary: {
+        jlongArray longArray = (*env)->GetObjectField(env, variant, jVariantLongArray);
+        jobjectArray objectArray = (*env)->GetObjectField(env, variant, jVariantVariantArray);
+        NSArray* keys = jArrayToNSArray(env, longArray, jLongToID);
+        NSArray* values = jArrayToNSArray(env, objectArray, jVariantToID);
+        if (keys != NULL && values != NULL && [keys count] == [values count]) {
+            return [NSDictionary dictionaryWithObjects: values forKeys: keys]; 
+        }
+        return NULL;
+    }
     case com_sun_glass_ui_mac_MacVariant_NSAttributedString: {
         jstring string = (*env)->GetObjectField(env, variant, jVariantString);
         NSString* nsString = jStringToNSString(env, string);
         if (nsString == NULL) return NULL;
-        NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:nsString];
+        NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:nsString];
+        jobjectArray stylesArray = (*env)->GetObjectField(env, variant, jVariantVariantArray);
+        if (stylesArray) {
+            /* Do not use GetPrimitiveArrayCritical for stylesArray */
+            jsize stylesCount = (*env)->GetArrayLength(env, stylesArray);
+
+            for (jsize index = 0; index < stylesCount; index++) {
+                /* jStyle is a special MacVariant with key, location, and length */
+                jobject jStyle = (*env)->GetObjectArrayElement(env, stylesArray, index);
+                if ((*env)->ExceptionCheck(env)) return NULL;
+                id value = variantToID(env, jStyle);
+                if (value) {
+                    jint location = (*env)->GetIntField(env, jStyle, jVariantLocation);
+                    jint length = (*env)->GetIntField(env, jStyle, jVariantLength);
+                    jlong key = (*env)->GetLongField(env, jStyle, jVariantKey);
+                    if (key) {
+                        [attrString addAttribute: (NSString *)key value: value range: NSMakeRange(location, length)];
+                    }
+                }
+            }
+        }
         return [attrString autorelease];
     }
     case com_sun_glass_ui_mac_MacVariant_NSValue_point: {
@@ -299,6 +338,13 @@
         jfloat height = (*env)->GetFloatField(env, variant, jVariantFloat2);
         return [NSValue valueWithSize: NSMakeSize(width, height)];
     }
+    case com_sun_glass_ui_mac_MacVariant_NSValue_rectangle: {
+        jfloat x = (*env)->GetFloatField(env, variant, jVariantFloat1);
+        jfloat y = (*env)->GetFloatField(env, variant, jVariantFloat2);
+        jfloat width = (*env)->GetFloatField(env, variant, jVariantFloat3);
+        jfloat height = (*env)->GetFloatField(env, variant, jVariantFloat4);
+        return [NSValue valueWithRect: NSMakeRect(x, y, width, height)];
+    }
     case com_sun_glass_ui_mac_MacVariant_NSValue_range: {
         jint start = (*env)->GetIntField(env, variant, jVariantInt1);
         jint length = (*env)->GetIntField(env, variant, jVariantInt2);
@@ -441,10 +487,22 @@
         if ((*env)->ExceptionCheck(env)) return;
         jVariantFloat2 = (*env)->GetFieldID(env, jVariantClass, "float2", "F");
         if ((*env)->ExceptionCheck(env)) return;
+        jVariantFloat3 = (*env)->GetFieldID(env, jVariantClass, "float3", "F");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantFloat4 = (*env)->GetFieldID(env, jVariantClass, "float4", "F");
+        if ((*env)->ExceptionCheck(env)) return;
         jVariantDouble1 = (*env)->GetFieldID(env, jVariantClass, "double1", "D");
         if ((*env)->ExceptionCheck(env)) return;
         jVariantString = (*env)->GetFieldID(env, jVariantClass, "string", "Ljava/lang/String;");
         if ((*env)->ExceptionCheck(env)) return;
+        jVariantVariantArray = (*env)->GetFieldID(env, jVariantClass, "variantArray", "[Lcom/sun/glass/ui/mac/MacVariant;");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantLocation = (*env)->GetFieldID(env, jVariantClass, "location", "I");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantLength = (*env)->GetFieldID(env, jVariantClass, "length", "I");
+        if ((*env)->ExceptionCheck(env)) return;
+        jVariantKey = (*env)->GetFieldID(env, jVariantClass, "key", "J");
+        if ((*env)->ExceptionCheck(env)) return;
     }
 
     jLongToID = ^(void* data, CFIndex index) {
@@ -453,7 +511,10 @@
 
     jIntToNSNumber = ^(void* data, CFIndex index) {
         return (id)[NSNumber numberWithInt: ((jint*)data)[index]];
-    };    
+    };
+
+    /* Special case, handled internally in jArrayToNSArray() */
+    jVariantToID = NULL;
 }
 
 /*
@@ -517,7 +578,7 @@
         NSString* n = (NSString*)id;
         jstring value = (*env)->NewStringUTF(env, [n UTF8String]);
         if (value) {
-        	(*env)->SetObjectField(env, jVariant, jVariantString, value);
+            (*env)->SetObjectField(env, jVariant, jVariantString, value);
         }
         break;
     }
@@ -526,14 +587,14 @@
         NSUInteger count = [n count];
         jlongArray result = (*env)->NewLongArray(env, count);
         if (result) {
-	        jlong* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
-	        if (data) {
-		        for (NSUInteger index = 0; index < count; index++) {
-		            data[index] = (jlong) [n objectAtIndex: index];
-		        }
-		        (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
-     	        (*env)->SetObjectField(env, jVariant, jVariantLongArray, result);
-		    }
+            jlong* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
+            if (data) {
+                for (NSUInteger index = 0; index < count; index++) {
+                    data[index] = (jlong) [n objectAtIndex: index];
+                }
+                (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
+                (*env)->SetObjectField(env, jVariant, jVariantLongArray, result);
+            }
         }
         break;
     }
@@ -542,16 +603,16 @@
         NSUInteger count = [n count];
         jintArray result = (*env)->NewIntArray(env, count);
         if (result) {
-	        jint* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
-	        if (data) {
-		        for (NSUInteger index = 0; index < count; index++) {
-		            NSNumber* value = (NSNumber*)[n objectAtIndex: index];
-		            data[index] = [value intValue];
-		        }
-		        (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
-		        (*env)->SetObjectField(env, jVariant, jVariantIntArray, result);
-		    }
-	    }
+            jint* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
+            if (data) {
+                for (NSUInteger index = 0; index < count; index++) {
+                    NSNumber* value = (NSNumber*)[n objectAtIndex: index];
+                    data[index] = [value intValue];
+                }
+                (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
+                (*env)->SetObjectField(env, jVariant, jVariantIntArray, result);
+            }
+        }
         break;
     }
     case com_sun_glass_ui_mac_MacVariant_NSValue_point: {
@@ -559,18 +620,30 @@
         NSPoint value = [n pointValue];
         (*env)->SetFloatField(env, jVariant, jVariantFloat1, value.x);
         (*env)->SetFloatField(env, jVariant, jVariantFloat2, value.y);
+        break;
     }
     case com_sun_glass_ui_mac_MacVariant_NSValue_size: {
         NSValue* n = (NSValue*)id;
         NSSize value = [n sizeValue];
         (*env)->SetFloatField(env, jVariant, jVariantFloat1, value.width);
         (*env)->SetFloatField(env, jVariant, jVariantFloat2, value.height);
+        break;
+    }
+    case com_sun_glass_ui_mac_MacVariant_NSValue_rectangle: {
+        NSValue* n = (NSValue*)id;
+        NSRect value = [n rectValue];
+        (*env)->SetFloatField(env, jVariant, jVariantFloat1, value.origin.x);
+        (*env)->SetFloatField(env, jVariant, jVariantFloat2, value.origin.y);
+        (*env)->SetFloatField(env, jVariant, jVariantFloat3, value.size.width);
+        (*env)->SetFloatField(env, jVariant, jVariantFloat4, value.size.height);
+        break;
     }
     case com_sun_glass_ui_mac_MacVariant_NSValue_range: {
         NSValue* n = (NSValue*)id;
         NSRange value = [n rangeValue];
         (*env)->SetIntField(env, jVariant, jVariantInt1, value.location);
         (*env)->SetIntField(env, jVariant, jVariantInt2, value.length);
+        break;
     }
     }
     return jVariant;
@@ -603,14 +676,14 @@
     NSUInteger count = [n count];
     jlongArray result = (*env)->NewLongArray(env, count);
     if (result) {
-	    jlong* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
-	    if (data) {
-		    for (NSUInteger index = 0; index < count; index++) {
-		        data[index] = (jlong) [n objectAtIndex: index];
-		    }
-		}
-	    (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
-	}
+        jlong* data = (*env)->GetPrimitiveArrayCritical(env, result, 0);
+        if (data) {
+            for (NSUInteger index = 0; index < count; index++) {
+                data[index] = (jlong) [n objectAtIndex: index];
+            }
+        }
+        (*env)->ReleasePrimitiveArrayCritical(env, result, data, 0);
+    }
     return result;
 }
 
--- a/modules/graphics/src/main/native-glass/mac/GlassApplication.m	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassApplication.m	Thu Apr 24 10:37:43 2014 -0700
@@ -533,7 +533,7 @@
                 [app setDelegate:self];
 
                 // [app activateIgnoringOtherApps:YES] won't activate the menu bar on OS X 10.9, so instead we do this:
-                [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+                [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)];
             }
             else
             {
--- a/modules/graphics/src/main/native-glass/mac/GlassMenu.m	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/mac/GlassMenu.m	Thu Apr 24 10:37:43 2014 -0700
@@ -88,6 +88,9 @@
                                                                    keyEquivalent:@""];
         [self->item setEnabled:(BOOL)jenabled];
         [self->item setTarget:self];
+
+        self->menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:[self->item title]];
+        [self->menu setDelegate: self];
     }
     return self;
 }
@@ -162,7 +165,7 @@
 }
 
 
-- (void)menuWillOpen: (NSMenu *)menu
+- (void)menuNeedsUpdate: (NSMenu *)menu
 {
     GET_MAIN_JENV;
     if (env != NULL)
@@ -194,7 +197,7 @@
         (*env)->CallVoidMethod(env, self->jCallback, jMenuValidateMethod, NULL);
 
         return ([glassTargetItem->item isEnabled]);
-    } 
+    }
     return YES;
 }
 
@@ -432,11 +435,6 @@
     GLASS_POOL_ENTER;
     {
         GlassMenu *menu = (GlassMenu *)jlong_to_ptr(jMenuPtr);
-        if (menu->menu == nil)
-        {
-            menu->menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:[menu->item title]];
-            [menu->menu setDelegate: menu];
-        }
 
         if (jSubmenuPtr != 0)
         {
--- a/modules/graphics/src/main/native-glass/win/GlassAccessible.cpp	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/win/GlassAccessible.cpp	Thu Apr 24 10:37:43 2014 -0700
@@ -125,13 +125,57 @@
 static jfieldID fid_bstrVal;
 static jfieldID fid_pDblVal;
 
-/* static */ void GlassAccessible::copyVariant(JNIEnv *env, jobject jVariant, VARIANT* pRetVal)
+
+/* static */ HRESULT GlassAccessible::copyString(JNIEnv *env, jstring jString, BSTR* pbstrVal)
 {
-    if (pRetVal == NULL) return;
+    if (pbstrVal != NULL) {
+        UINT length = env->GetStringLength(jString);
+        const jchar* ptr = env->GetStringCritical(jString, NULL);
+        if (ptr != NULL) {
+            *pbstrVal = SysAllocStringLen(reinterpret_cast<const OLECHAR *>(ptr), length);
+            env->ReleaseStringCritical(jString, ptr);
+            return S_OK;
+        }
+    }
+    return E_FAIL;
+}
+
+/* static */ HRESULT GlassAccessible::copyList(JNIEnv *env, jarray list, SAFEARRAY** pparrayVal, VARTYPE vt)
+{
+    if (list) {
+        jsize size = env->GetArrayLength(list);
+        SAFEARRAY *psa = SafeArrayCreateVector(vt, 0, size);
+        if (psa) {
+            void* listPtr = env->GetPrimitiveArrayCritical(list, 0);
+            jint* intPtr = (jint*)listPtr;
+            jlong* longPtr = (jlong*)listPtr;
+            jdouble* doublePtr = (jdouble*)listPtr;
+            for (LONG i = 0; i < size; i++) {
+                if (vt == VT_UNKNOWN) {
+                    //TODO make sure AddRef on elements is not required ?
+                    SafeArrayPutElement(psa, &i,  (void*)longPtr[i]);
+                } else if (vt == VT_I4){
+                    SafeArrayPutElement(psa, &i, (void*)&(intPtr[i]));
+                } else if (vt == VT_R8){
+                    SafeArrayPutElement(psa, &i, (void*)&(doublePtr[i]));
+                }
+            }
+            env->ReleasePrimitiveArrayCritical(list, listPtr, 0);
+            *pparrayVal = psa;
+            return S_OK;
+        }
+    }
+    return E_FAIL;
+}
+
+/* static */ HRESULT GlassAccessible::copyVariant(JNIEnv *env, jobject jVariant, VARIANT* pRetVal)
+{
+    if (pRetVal == NULL) return E_FAIL;
     if (jVariant == NULL) {
         pRetVal->vt = VT_EMPTY;
-        return;
+        return E_FAIL;
     }
+    HRESULT hr = S_OK;
     pRetVal->vt = (VARTYPE)env->GetShortField(jVariant, fid_vt);
     switch (pRetVal->vt) {
         case VT_I2:
@@ -145,7 +189,7 @@
             if (pRetVal->punkVal != NULL) {
                 pRetVal->punkVal->AddRef();
             } else {
-                pRetVal->vt = VT_EMPTY;
+                hr = E_FAIL;
             }
             break;
         case VT_R4:
@@ -161,85 +205,42 @@
         }
         case VT_BSTR: {
             jstring str = (jstring)env->GetObjectField(jVariant, fid_bstrVal);
-            if (str != NULL) {
-                UINT length = env->GetStringLength(str);
-                const jchar* ptr = env->GetStringCritical(str, NULL);
-                if (ptr != NULL) {
-					pRetVal->bstrVal = SysAllocStringLen(reinterpret_cast<const OLECHAR *>(ptr), length);
-					env->ReleaseStringCritical(str, ptr);
-                }
-            }
-            if (pRetVal->parray == NULL) {
-                pRetVal->vt = VT_EMPTY;
-            }
+            hr = GlassAccessible::copyString(env, str, &(pRetVal->bstrVal));
             break;
         }
         case VT_R8 | VT_ARRAY: {
             jarray list = (jarray)env->GetObjectField(jVariant, fid_pDblVal);
-            pRetVal->parray = NULL;
-            if (list) {
-                jsize size = env->GetArrayLength(list);
-                SAFEARRAY *psa = SafeArrayCreateVector(VT_R8, 0, size);
-                if (psa) {
-                    jdouble* listPtr = (jdouble*)env->GetPrimitiveArrayCritical(list, 0);
-                    if (listPtr != NULL) {
-						for (LONG i = 0; i < size; i++) {
-							SafeArrayPutElement(psa, &i, (void*)&(listPtr[i]));
-						}
-						env->ReleasePrimitiveArrayCritical(list, listPtr, 0);
-						pRetVal->parray = psa;
-                    }
-                }
-            }
-            if (pRetVal->parray == NULL) {
-                pRetVal->vt = VT_EMPTY;
-            }
+            hr = GlassAccessible::copyList(env, list, &(pRetVal->parray), VT_R8);
             break;
         }
     }
+    if (FAILED(hr)) pRetVal->vt = VT_EMPTY;
+    return hr;
 }
 
-jlong GlassAccessible::callLongMethod(jmethodID mid, ...)
+HRESULT GlassAccessible::callLongMethod(jmethodID mid,  IUnknown **pRetVal, ...)
 {
     va_list vl;
-    va_start(vl, mid);
+    va_start(vl, pRetVal);
     JNIEnv* env = GetEnv();
     jlong ptr = env->CallLongMethodV(m_jAccessible, mid, vl);
-    CheckAndClearException(env);
     va_end(vl);
+    if (CheckAndClearException(env)) return E_FAIL;
 
     /* AddRef the result */
     IUnknown* iUnknown = reinterpret_cast<IUnknown*>(ptr);
     if (iUnknown) iUnknown->AddRef();
-
-    return ptr;
+    *pRetVal = iUnknown;
+    return S_OK;
 }
 
-SAFEARRAY* GlassAccessible::callArrayMethod(jmethodID mid, VARTYPE vt)
+HRESULT GlassAccessible::callArrayMethod(jmethodID mid, VARTYPE vt, SAFEARRAY **pRetVal)
 {
     JNIEnv* env = GetEnv();
     jarray list = (jarray)env->CallObjectMethod(m_jAccessible, mid);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    if (list) {
-        jsize size = env->GetArrayLength(list);
-        SAFEARRAY *psa = SafeArrayCreateVector(vt, 0, size);
-        if (psa) {
-            jint* listPtr = (jint*)env->GetPrimitiveArrayCritical(list, 0);
-            for (LONG i = 0; i < size; i++) {
-                if (vt == VT_UNKNOWN) {
-                    //TODO make sure AddRef on elements is not required ?
-                    SafeArrayPutElement(psa, &i, (void*)listPtr[i]);
-                } else {
-                    SafeArrayPutElement(psa, &i, (void*)&(listPtr[i]));
-                }
-
-            }
-            env->ReleasePrimitiveArrayCritical(list, listPtr, 0);
-        }
-        return psa;
-    }
-    return NULL;
+    return GlassAccessible::copyList(env, list, pRetVal, vt);
 }
 
 GlassAccessible::GlassAccessible(JNIEnv* env, jobject jAccessible)
@@ -328,7 +329,7 @@
     if (pRetVal == NULL) return E_INVALIDARG;
     JNIEnv* env = GetEnv();
     jlong hwnd = env->CallLongMethod(m_jAccessible, mid_get_HostRawElementProvider);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     
     // We ignore the return value of UiaHostProviderFromHwnd because it returns E_INVALIDARG
     // when invoked with NULL hwnd. We use NULL hwnds to represent "lightweight" accessibles.
@@ -353,9 +354,7 @@
 IFACEMETHODIMP GlassAccessible::GetPatternProvider(PATTERNID patternId, IUnknown** pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_GetPatternProvider, patternId);
-    *pRetVal = reinterpret_cast<IUnknown*>(ptr);
-    return S_OK;
+    return callLongMethod(mid_GetPatternProvider, pRetVal, patternId);
 }
 
 IFACEMETHODIMP GlassAccessible::GetPropertyValue(PROPERTYID propertyId, VARIANT* pRetVal)
@@ -363,10 +362,9 @@
     if (pRetVal == NULL) return E_INVALIDARG;
     JNIEnv* env = GetEnv();
     jobject jVariant = env->CallObjectMethod(m_jAccessible, mid_GetPropertyValue, propertyId);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    copyVariant(env, jVariant, pRetVal);
-    return S_OK;
+    return copyVariant(env, jVariant, pRetVal);
 }
 
 /***********************************************/
@@ -377,7 +375,7 @@
     if (pRetVal == NULL) return E_INVALIDARG;
     JNIEnv* env = GetEnv();
     jfloatArray bounds = (jfloatArray)env->CallObjectMethod(m_jAccessible, mid_get_BoundingRectangle);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
     if (bounds) {
         jfloat* boundsPtr = (jfloat*)env->GetPrimitiveArrayCritical(bounds, 0);
@@ -393,38 +391,38 @@
 IFACEMETHODIMP GlassAccessible::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_get_FragmentRoot);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_get_FragmentRoot, &ptr);
     *pRetVal = reinterpret_cast<IRawElementProviderFragmentRoot*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 IFACEMETHODIMP GlassAccessible::GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetEmbeddedFragmentRoots, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetEmbeddedFragmentRoots, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::GetRuntimeId(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetRuntimeId, VT_I4);
-    return S_OK;
+    return callArrayMethod(mid_GetRuntimeId, VT_I4, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_Navigate, direction);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_Navigate, &ptr, direction);
     *pRetVal = reinterpret_cast<IRawElementProviderFragment*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 IFACEMETHODIMP GlassAccessible::SetFocus()
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_SetFocus);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -434,17 +432,19 @@
 IFACEMETHODIMP GlassAccessible::ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_ElementProviderFromPoint, x, y);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_ElementProviderFromPoint, &ptr, x, y);
     *pRetVal = reinterpret_cast<IRawElementProviderFragment*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 IFACEMETHODIMP GlassAccessible::GetFocus(IRawElementProviderFragment **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_GetFocus);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_GetFocus, &ptr);
     *pRetVal = reinterpret_cast<IRawElementProviderFragment*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 /***********************************************/
@@ -454,7 +454,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Invoke);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -464,15 +464,14 @@
 IFACEMETHODIMP GlassAccessible::GetSelection(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetSelection, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetSelection, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::get_CanSelectMultiple(BOOL *pRetVal)
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_CanSelectMultiple);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -480,7 +479,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_IsSelectionRequired);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -491,7 +490,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Select);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -499,7 +498,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_AddToSelection);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -507,7 +506,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_RemoveFromSelection);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -515,16 +514,17 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_IsSelected);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
 IFACEMETHODIMP GlassAccessible::get_SelectionContainer(IRawElementProviderSimple **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_get_SelectionContainer);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_get_SelectionContainer, &ptr);
     *pRetVal = reinterpret_cast<IRawElementProviderSimple*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 /***********************************************/
@@ -534,7 +534,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_SetValue, val);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -542,7 +542,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_Value);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -550,7 +550,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_IsReadOnly);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -558,7 +558,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_Maximum);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -566,7 +566,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_Minimum);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -574,7 +574,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_LargeChange);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -582,7 +582,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_SmallChange);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -597,7 +597,7 @@
     jstring str = env->NewString((const jchar *)val, (jsize)size);
     if (!CheckAndClearException(env)) {
     	env->CallVoidMethod(m_jAccessible, mid_SetValueString, str);
-    	CheckAndClearException(env);
+    	if (CheckAndClearException(env)) return E_FAIL;
     }
     return S_OK;
 }
@@ -606,18 +606,9 @@
 {
     JNIEnv* env = GetEnv();
     jstring str = (jstring)env->CallObjectMethod(m_jAccessible, mid_get_ValueString);
-    CheckAndClearException(env);
-    if (str) {
-        UINT length = env->GetStringLength(str);
-        const jchar* ptr = env->GetStringCritical(str, NULL);
-        if (ptr != NULL) {
-        	*pRetVal = SysAllocStringLen(reinterpret_cast<const OLECHAR *>(ptr), length);
-        	env->ReleaseStringCritical(str, ptr);
-        }
-    } else {
-        *pRetVal = NULL;
-    }
-    return S_OK;
+    if (CheckAndClearException(env)) return E_FAIL;
+
+    return GlassAccessible::copyString(env, str, pRetVal);
 }
 
 /***********************************************/
@@ -626,14 +617,23 @@
 IFACEMETHODIMP GlassAccessible::GetVisibleRanges(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetVisibleRanges, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetVisibleRanges, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::RangeFromChild(IRawElementProviderSimple *childElement,  ITextRangeProvider **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_RangeFromChild, (jlong)childElement);
+    JNIEnv* env = GetEnv();
+    jlong ptr = env->CallLongMethod(m_jAccessible, mid_RangeFromChild, (jlong)childElement);
+    if (CheckAndClearException(env)) return E_FAIL;
+
+    /* This code is intentionally commented.
+     * JavaFX returns a new ITextRangeProvider instance each time.
+     * The caller holds the only reference to this object.
+     */
+//    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
+//    if (iUnknown) iUnknown->AddRef();
+
     *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
     return S_OK;
 }
@@ -641,7 +641,17 @@
 IFACEMETHODIMP GlassAccessible::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_RangeFromPoint, point.x, point.y);
+    JNIEnv* env = GetEnv();
+    jlong ptr = env->CallLongMethod(m_jAccessible, mid_RangeFromPoint, point.x, point.y);
+    if (CheckAndClearException(env)) return E_FAIL;
+
+    /* This code is intentionally commented.
+     * JavaFX returns a new ITextRangeProvider instance each time.
+     * The caller holds the only reference to this object.
+     */
+//    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
+//    if (iUnknown) iUnknown->AddRef();
+
     *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
     return S_OK;
 }
@@ -649,16 +659,17 @@
 IFACEMETHODIMP GlassAccessible::get_DocumentRange(ITextRangeProvider **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_get_DocumentRange);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_get_DocumentRange, &ptr);
     *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 IFACEMETHODIMP GlassAccessible::get_SupportedTextSelection(SupportedTextSelection *pRetVal)
 {
     JNIEnv* env = GetEnv();
     *pRetVal = (SupportedTextSelection)env->CallIntMethod(m_jAccessible, mid_get_SupportedTextSelection);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -669,22 +680,23 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_ColumnCount);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
 IFACEMETHODIMP GlassAccessible::get_RowCount(int *pRetVal) {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_RowCount);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
 IFACEMETHODIMP GlassAccessible::GetItem(int row, int column, IRawElementProviderSimple **pRetVal) {
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_GetItem, row, column);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_GetItem, &ptr, row, column);
     *pRetVal = reinterpret_cast<IRawElementProviderSimple*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 /***********************************************/
@@ -693,7 +705,7 @@
 IFACEMETHODIMP GlassAccessible::get_Column(int *pRetVal) {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_Column);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -701,29 +713,30 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_ColumnSpan);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
 IFACEMETHODIMP GlassAccessible::get_ContainingGrid(IRawElementProviderSimple **pRetVal){
     if (pRetVal == NULL) return E_INVALIDARG;
-    jlong ptr = callLongMethod(mid_get_ContainingGrid);
+    IUnknown* ptr = NULL;
+    HRESULT hr = callLongMethod(mid_get_ContainingGrid, &ptr);
     *pRetVal = reinterpret_cast<IRawElementProviderSimple*>(ptr);
-    return S_OK;
+    return hr;
 }
 
 IFACEMETHODIMP GlassAccessible::get_Row(int *pRetVal)
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_Row);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
 IFACEMETHODIMP GlassAccessible::get_RowSpan(int *pRetVal) {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jAccessible, mid_get_RowSpan);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -733,21 +746,19 @@
 IFACEMETHODIMP GlassAccessible::GetColumnHeaders(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetColumnHeaders, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetColumnHeaders, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::GetRowHeaders(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetRowHeaders, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetRowHeaders, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::get_RowOrColumnMajor(RowOrColumnMajor *pRetVal) {
     JNIEnv* env = GetEnv();
     *pRetVal = (RowOrColumnMajor) env->CallIntMethod(m_jAccessible, mid_get_RowOrColumnMajor);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -758,15 +769,13 @@
 IFACEMETHODIMP GlassAccessible::GetColumnHeaderItems(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetColumnHeaderItems, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetColumnHeaderItems, VT_UNKNOWN, pRetVal);
 }
 
 IFACEMETHODIMP GlassAccessible::GetRowHeaderItems(SAFEARRAY **pRetVal)
 {
     if (pRetVal == NULL) return E_INVALIDARG;
-    *pRetVal = callArrayMethod(mid_GetRowHeaderItems, VT_UNKNOWN);
-    return S_OK;
+    return callArrayMethod(mid_GetRowHeaderItems, VT_UNKNOWN, pRetVal);
 }
 
 
@@ -777,7 +786,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Toggle);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -785,7 +794,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = (ToggleState) env->CallIntMethod(m_jAccessible, mid_get_ToggleState);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -796,7 +805,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Collapse);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -804,7 +813,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Expand);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -812,7 +821,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = (ExpandCollapseState) env->CallIntMethod(m_jAccessible, mid_get_ExpandCollapseState);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -823,7 +832,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_CanMove);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -831,7 +840,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_CanResize);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -839,7 +848,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_CanRotate);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -847,7 +856,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Move, x, y);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -855,7 +864,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Resize, width, height);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -863,7 +872,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Rotate, degrees);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -874,7 +883,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_Scroll, horizontalAmount, verticalAmount);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -882,7 +891,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_SetScrollPercent, horizontalPercent, verticalPercent);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -890,7 +899,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_HorizontallyScrollable);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -898,7 +907,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_HorizontalScrollPercent);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -906,7 +915,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_HorizontalViewSize);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -914,7 +923,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jAccessible, mid_get_VerticallyScrollable);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -922,7 +931,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_VerticalScrollPercent);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -930,7 +939,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallDoubleMethod(m_jAccessible, mid_get_VerticalViewSize);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -941,7 +950,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jAccessible, mid_ScrollIntoView);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -1172,7 +1181,6 @@
 {
     GlassAccessible* acc = reinterpret_cast<GlassAccessible*>(winAccessible);
     acc->Release();
-//    delete acc;
 }
 
 /*
@@ -1197,9 +1205,12 @@
 {
     IRawElementProviderSimple* pProvider = reinterpret_cast<IRawElementProviderSimple*>(jAccessible);
     VARIANT ov = {0}, nv = {0};
+    HRESULT hr = E_FAIL;
 
-    GlassAccessible::copyVariant(env, oldV, &ov);
-    GlassAccessible::copyVariant(env, newV, &nv);
+    hr = GlassAccessible::copyVariant(env, oldV, &ov);
+    if (FAILED(hr)) return (jlong)hr;
+    hr = GlassAccessible::copyVariant(env, newV, &nv);
+    if (FAILED(hr)) return (jlong)hr;
 
     return (jlong)UiaRaiseAutomationPropertyChangedEvent(pProvider, (PROPERTYID)id, ov, nv);
 }
--- a/modules/graphics/src/main/native-glass/win/GlassAccessible.h	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/win/GlassAccessible.h	Thu Apr 24 10:37:43 2014 -0700
@@ -162,16 +162,18 @@
     // IScrollItemProvider
     IFACEMETHODIMP ScrollIntoView();
 
-    static void copyVariant(JNIEnv *env, jobject jVariant, VARIANT* pRetVal);
+    static HRESULT copyVariant(JNIEnv *env, jobject jVariant, VARIANT* pRetVal);
+    static HRESULT copyString(JNIEnv *env, jstring jString, BSTR* pbstrVal);
+    static HRESULT copyList(JNIEnv *env, jarray list, SAFEARRAY** pparrayVal, VARTYPE vt);
 
 private:
     virtual ~GlassAccessible();
 
     /* Call the method specified by 'mid', AddRef the returning ptr (expects result to be IUnkonwn) */
-    virtual jlong callLongMethod(jmethodID mid, ...);
+    virtual HRESULT callLongMethod(jmethodID mid, IUnknown **pRetVal, ...);
 
     /* Call the method specified by 'mid' and converts the returning jarray to a SAFEARRAY */
-    virtual SAFEARRAY* callArrayMethod(jmethodID mid, VARTYPE vt);
+    virtual HRESULT callArrayMethod(jmethodID mid, VARTYPE vt, SAFEARRAY **pRetVal);
 
     ULONG m_refCount;
     jobject m_jAccessible;  // The GlobalRef Java side object
--- a/modules/graphics/src/main/native-glass/win/GlassTextRangeProvider.cpp	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-glass/win/GlassTextRangeProvider.cpp	Thu Apr 24 10:37:43 2014 -0700
@@ -27,6 +27,7 @@
 #include "common.h"
 #include "com_sun_glass_ui_win_WinTextRangeProvider.h"
 #include "GlassTextRangeProvider.h"
+#include "GlassAccessible.h"
 
 /* TextRangeProvider Method IDs */
 static jmethodID mid_Clone;
@@ -102,11 +103,16 @@
 {
     JNIEnv* env = GetEnv();
     jlong ptr = env->CallLongMethod(m_jTextRangeProvider, mid_Clone);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
-//    if (iUnknown) iUnknown->AddRef(); /* The refcount of the a new object is one. Do we want to keep a reference to this guy ? */
-    *pRetVal = iUnknown;
+    /* This code is intentionally commented.
+     * JavaFX returns a new ITextRangeProvider instance each time.
+     * The caller holds the only reference to this object.
+     */
+//    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
+//    if (iUnknown) iUnknown->AddRef();
+
+    *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
     return S_OK;
 }
 
@@ -114,12 +120,12 @@
 {
     GlassTextRangeProvider* glassRange = reinterpret_cast<GlassTextRangeProvider*>(range);
     if (glassRange == NULL ||  glassRange->m_jTextRangeProvider == NULL) {
-        *pRetVal = FALSE; /* Can't compare against an unknown object */
+        *pRetVal = FALSE;
         return S_OK;
     }
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallBooleanMethod(m_jTextRangeProvider, mid_Compare, glassRange->m_jTextRangeProvider);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -128,12 +134,12 @@
 {
     GlassTextRangeProvider* glassRange = reinterpret_cast<GlassTextRangeProvider*>(targetRange);
     if (glassRange == NULL ||  glassRange->m_jTextRangeProvider == NULL) {
-        *pRetVal = FALSE; /* Can't compare against an unknown object */
+        *pRetVal = FALSE;
         return S_OK;
     }
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jTextRangeProvider, mid_CompareEndpoints, endpoint, glassRange->m_jTextRangeProvider, targetEndpoint);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -141,7 +147,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_ExpandToEnclosingUnit, unit);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -151,53 +157,65 @@
     jobject jVal = NULL;
     JNIEnv* env = GetEnv();
     jlong ptr = env->CallLongMethod(m_jTextRangeProvider, mid_FindAttribute, attributeId, jVal, backward);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO AddRef ptr
+    /* This code is intentionally commented.
+     * JavaFX returns a new ITextRangeProvider instance each time.
+     * The caller holds the only reference to this object.
+     */
+//    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
+//    if (iUnknown) iUnknown->AddRef();
+
     *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
     return S_OK;
 }
 
 IFACEMETHODIMP GlassTextRangeProvider::FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal)
 {
-    //TODO TEXT TO JTEXT
-    jstring jText = NULL;
     JNIEnv* env = GetEnv();
+    jsize length = SysStringLen(text);
+    jstring jText = env->NewString((const jchar *)text, length);
     jlong ptr = env->CallLongMethod(m_jTextRangeProvider, mid_FindText, jText, backward, ignoreCase);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO AddRef ptr
+    /* This code is intentionally commented.
+     * JavaFX returns a new ITextRangeProvider instance each time.
+     * The caller holds the only reference to this object.
+     */
+//    ITextRangeProvider* iUnknown = reinterpret_cast<ITextRangeProvider*>(ptr);
+//    if (iUnknown) iUnknown->AddRef();
+
     *pRetVal = reinterpret_cast<ITextRangeProvider*>(ptr);
     return S_OK;
 }
 IFACEMETHODIMP GlassTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal)
 {
     JNIEnv* env = GetEnv();
-    jobject jval = env->CallObjectMethod(m_jTextRangeProvider, mid_GetAttributeValue, attributeId);
-    CheckAndClearException(env);
+    jobject jVariant = env->CallObjectMethod(m_jTextRangeProvider, mid_GetAttributeValue, attributeId);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO jval to val
-//    *pRetVal =
-    return S_OK;
+    return GlassAccessible::copyVariant(env, jVariant, pRetVal);
 }
 
-IFACEMETHODIMP GlassTextRangeProvider::GetBoundingRectangles(SAFEARRAY * *pRetVal)
+IFACEMETHODIMP GlassTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal)
 {
     JNIEnv* env = GetEnv();
     jarray bounds = (jarray)env->CallObjectMethod(m_jTextRangeProvider, mid_GetBoundingRectangles);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO bounds to SAFEARRAY
-    return S_OK;
+    return GlassAccessible::copyList(env, bounds, pRetVal, VT_R8);
 }
 
 IFACEMETHODIMP GlassTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal)
 {
     JNIEnv* env = GetEnv();
     jlong ptr = env->CallLongMethod(m_jTextRangeProvider, mid_GetEnclosingElement);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO AddRef ptr
+    /* AddRef the result */
+    IUnknown* iUnknown = reinterpret_cast<IUnknown*>(ptr);
+    if (iUnknown) iUnknown->AddRef();
+
     *pRetVal = reinterpret_cast<IRawElementProviderSimple*>(ptr);
     return S_OK;
 }
@@ -206,17 +224,16 @@
 {
     JNIEnv* env = GetEnv();
     jstring string = (jstring)env->CallObjectMethod(m_jTextRangeProvider, mid_GetText, maxLength);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO String to BSTR*
-    return S_OK;
+    return GlassAccessible::copyString(env, string, pRetVal);
 }
 
 IFACEMETHODIMP GlassTextRangeProvider::Move(TextUnit unit, int count, int *pRetVal)
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jTextRangeProvider, mid_Move, unit, count);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -224,7 +241,7 @@
 {
     JNIEnv* env = GetEnv();
     *pRetVal = env->CallIntMethod(m_jTextRangeProvider, mid_MoveEndpointByUnit, endpoint, unit, count);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -232,10 +249,13 @@
                                                            TextPatternRangeEndpoint targetEndpoint)
 {
 
-    GlassTextRangeProvider* glassRange = reinterpret_cast<GlassTextRangeProvider*>(targetRange);//TODO is that okay ?
+    GlassTextRangeProvider* glassRange = reinterpret_cast<GlassTextRangeProvider*>(targetRange);
+    if (glassRange == NULL ||  glassRange->m_jTextRangeProvider == NULL) {
+        return S_OK;
+    }
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_MoveEndpointByRange, endpoint, glassRange->m_jTextRangeProvider, targetEndpoint);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -243,7 +263,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_Select);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -251,7 +271,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_AddToSelection);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -259,7 +279,7 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_RemoveFromSelection);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
@@ -267,18 +287,17 @@
 {
     JNIEnv* env = GetEnv();
     env->CallVoidMethod(m_jTextRangeProvider, mid_ScrollIntoView, alignToTop);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
     return S_OK;
 }
 
-IFACEMETHODIMP GlassTextRangeProvider::GetChildren(SAFEARRAY * *pRetVal)
+IFACEMETHODIMP GlassTextRangeProvider::GetChildren(SAFEARRAY **pRetVal)
 {
     JNIEnv* env = GetEnv();
     jarray children = (jarray)env->CallObjectMethod(m_jTextRangeProvider, mid_GetChildren);
-    CheckAndClearException(env);
+    if (CheckAndClearException(env)) return E_FAIL;
 
-    //TODO children to SAFEARRAY
-    return S_OK;
+    return GlassAccessible::copyList(env, children, pRetVal, VT_UNKNOWN);
 }
 
 /***********************************************/
--- a/modules/graphics/src/main/native-iio/libjpeg7/jchuff.c	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-iio/libjpeg7/jchuff.c	Thu Apr 24 10:37:43 2014 -0700
@@ -179,6 +179,9 @@
   unsigned int huffcode[257];
   unsigned int code;
 
+  MEMZERO(huffsize, SIZEOF(huffsize));
+  MEMZERO(huffcode, SIZEOF(huffcode));
+
   /* Note that huffsize[] and huffcode[] are filled in code-length order,
    * paralleling the order of the symbols themselves in htbl->huffval[].
    */
@@ -790,6 +793,8 @@
   JBLOCKROW block;
   int absvalues[DCTSIZE2];
 
+  MEMZERO(absvalues, SIZEOF(absvalues));
+
   entropy->next_output_byte = cinfo->dest->next_output_byte;
   entropy->free_in_buffer = cinfo->dest->free_in_buffer;
 
--- a/modules/graphics/src/main/native-iio/libjpeg7/jcmaster.c	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-iio/libjpeg7/jcmaster.c	Thu Apr 24 10:37:43 2014 -0700
@@ -320,8 +320,11 @@
   int * last_bitpos_ptr;
   int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
   /* -1 until that coefficient has been seen; then last Al for it */
+  MEMZERO(last_bitpos, SIZEOF(last_bitpos));
 #endif
 
+  MEMZERO(component_sent, SIZEOF(component_sent));
+
   if (cinfo->num_scans <= 0)
     ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
 
--- a/modules/graphics/src/main/native-iio/libjpeg7/jdhuff.c	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/graphics/src/main/native-iio/libjpeg7/jdhuff.c	Thu Apr 24 10:37:43 2014 -0700
@@ -285,6 +285,9 @@
   unsigned int huffcode[257];
   unsigned int code;
 
+  MEMZERO(huffsize, SIZEOF(huffsize));
+  MEMZERO(huffcode, SIZEOF(huffcode));
+
   /* Note that huffsize[] and huffcode[] are filled in code-length order,
    * paralleling the order of the symbols themselves in htbl->huffval[].
    */
--- a/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java	Thu Apr 24 10:37:43 2014 -0700
@@ -89,6 +89,7 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.ImageData;
 import org.eclipse.swt.graphics.PaletteData;
@@ -169,8 +170,23 @@
             control = control.getParent();
         };
     };
-    
-    private double scaleFactor = 1.0;
+
+    private double getScaleFactor() {
+        if (SWT.getPlatform().equals("cocoa")) {
+            if (windowField == null || screenMethod == null || backingScaleFactorMethod == null) {
+                return 1.0;
+            }
+            try {
+                Object nsWindow = windowField.get(this.getShell());
+                Object nsScreen = screenMethod.invoke(nsWindow);
+                Object bsFactor = backingScaleFactorMethod.invoke(nsScreen);
+                return ((Double) bsFactor).doubleValue();
+            } catch (Exception e) {
+                // FAIL silently should the reflection fail
+            }
+        }
+        return 1.0;
+    }
     
     private DropTarget dropTarget;
     
@@ -205,7 +221,7 @@
         return transfer;
     }
     
-    private static Field viewField;
+    private static Field windowField;
     private static Method windowMethod;
     private static Method screenMethod;
     private static Method backingScaleFactorMethod;
@@ -213,8 +229,8 @@
     static {
         if (SWT.getPlatform().equals("cocoa")) {
             try {
-                viewField = GCData.class.getDeclaredField("view");
-                viewField.setAccessible(true);
+                windowField = Shell.class.getDeclaredField("window");
+                windowField.setAccessible(true);
 
                 Class nsViewClass = Class.forName("org.eclipse.swt.internal.cocoa.NSView");            
                 windowMethod = nsViewClass.getDeclaredMethod("window");
@@ -476,6 +492,7 @@
         }
     }
 
+    double lastScaleFactor = 1.0;
     int lastWidth, lastHeight;
     IntBuffer lastPixelsBuf =  null;
     private void paintControl(PaintEvent pe) {
@@ -483,6 +500,13 @@
             return;
         }
 
+        double scaleFactor = getScaleFactor();
+        if (lastScaleFactor != scaleFactor) {
+            resizePixelBuffer(scaleFactor);
+            lastScaleFactor = scaleFactor;
+            scenePeer.setPixelScaleFactor((float)scaleFactor);
+        }
+
         // if we can't get the pixels, draw the bits that were there before
         IntBuffer buffer = pixelsBuf;
         int width = pWidth, height = pHeight;
@@ -531,31 +555,6 @@
         Image image = new Image(Display.getDefault(), imageData);
         pe.gc.drawImage(image, 0, 0, width, height, 0, 0, pWidth, pHeight);
         image.dispose();
-        
-        double newScaleFactor = getScaleFactor(pe.gc);
-        if (scaleFactor != newScaleFactor) {
-            resizePixelBuffer(newScaleFactor);
-            // The scene will request repaint.
-            scenePeer.setPixelScaleFactor((float)newScaleFactor);
-            scaleFactor = newScaleFactor;
-        }
-    }
-    
-    private double getScaleFactor(GC gc) {
-        double scale = 1.0;
-        if (SWT.getPlatform().equals("cocoa")) {
-            if (viewField != null && windowMethod != null && screenMethod != null && backingScaleFactorMethod != null) {
-                try {
-                    Object nsWindow = windowMethod.invoke(viewField.get(gc.getGCData()));
-                    Object nsScreen = screenMethod.invoke(nsWindow);
-                    Object bsFactor = backingScaleFactorMethod.invoke(nsScreen);
-                    scale = ((Double)bsFactor).doubleValue();
-                } catch (Exception e) {
-                    //Fail silently.  If we can't get the methods, then the current version of SWT has no retina support
-                }
-            }
-        }
-        return scale;
     }
     
     private void sendMoveEventToFX() {
@@ -655,7 +654,7 @@
         pWidth = getClientArea().width;
         pHeight = getClientArea().height;
 
-        resizePixelBuffer(scaleFactor);
+        resizePixelBuffer(lastScaleFactor);
 
         if (scenePeer == null) {
             return;
@@ -942,6 +941,10 @@
             if (pWidth > 0 && pHeight > 0) {
                 scenePeer.setSize(pWidth, pHeight);
             }
+            double scaleFactor = getScaleFactor();
+            resizePixelBuffer(scaleFactor);
+            lastScaleFactor = scaleFactor;
+            scenePeer.setPixelScaleFactor((float)scaleFactor);
             scenePeer.setDragStartListener((fxDragSource, dragAction) -> {
                 Platform.runLater(() -> {
                     DragSource dragSource = createDragSource(fxDragSource, dragAction);
--- a/netbeans/native-font/nbproject/Makefile-Debug.mk	Wed Apr 23 08:35:01 2014 -0700
+++ b/netbeans/native-font/nbproject/Makefile-Debug.mk	Thu Apr 24 10:37:43 2014 -0700
@@ -40,7 +40,9 @@
 	${OBJECTDIR}/_ext/1812479850/dfontdecoder.o \
 	${OBJECTDIR}/_ext/1812479850/directwrite.o \
 	${OBJECTDIR}/_ext/1812479850/fontpath.o \
-	${OBJECTDIR}/_ext/1812479850/fontpath_linux.o
+	${OBJECTDIR}/_ext/1812479850/fontpath_linux.o \
+	${OBJECTDIR}/_ext/1812479850/freetype.o \
+	${OBJECTDIR}/_ext/1812479850/pango.o
 
 
 # C Compiler Flags
@@ -97,6 +99,16 @@
 	${RM} "$@.d"
 	$(COMPILE.c) -g -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/fontpath_linux.o ../../modules/graphics/src/main/native-font/fontpath_linux.c
 
+${OBJECTDIR}/_ext/1812479850/freetype.o: ../../modules/graphics/src/main/native-font/freetype.c 
+	${MKDIR} -p ${OBJECTDIR}/_ext/1812479850
+	${RM} "$@.d"
+	$(COMPILE.c) -g -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/freetype.o ../../modules/graphics/src/main/native-font/freetype.c
+
+${OBJECTDIR}/_ext/1812479850/pango.o: ../../modules/graphics/src/main/native-font/pango.c 
+	${MKDIR} -p ${OBJECTDIR}/_ext/1812479850
+	${RM} "$@.d"
+	$(COMPILE.c) -g -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/pango.o ../../modules/graphics/src/main/native-font/pango.c
+
 # Subprojects
 .build-subprojects:
 
--- a/netbeans/native-font/nbproject/Makefile-Release.mk	Wed Apr 23 08:35:01 2014 -0700
+++ b/netbeans/native-font/nbproject/Makefile-Release.mk	Thu Apr 24 10:37:43 2014 -0700
@@ -40,7 +40,9 @@
 	${OBJECTDIR}/_ext/1812479850/dfontdecoder.o \
 	${OBJECTDIR}/_ext/1812479850/directwrite.o \
 	${OBJECTDIR}/_ext/1812479850/fontpath.o \
-	${OBJECTDIR}/_ext/1812479850/fontpath_linux.o
+	${OBJECTDIR}/_ext/1812479850/fontpath_linux.o \
+	${OBJECTDIR}/_ext/1812479850/freetype.o \
+	${OBJECTDIR}/_ext/1812479850/pango.o
 
 
 # C Compiler Flags
@@ -97,6 +99,16 @@
 	${RM} "$@.d"
 	$(COMPILE.c) -O2 -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/fontpath_linux.o ../../modules/graphics/src/main/native-font/fontpath_linux.c
 
+${OBJECTDIR}/_ext/1812479850/freetype.o: ../../modules/graphics/src/main/native-font/freetype.c 
+	${MKDIR} -p ${OBJECTDIR}/_ext/1812479850
+	${RM} "$@.d"
+	$(COMPILE.c) -O2 -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/freetype.o ../../modules/graphics/src/main/native-font/freetype.c
+
+${OBJECTDIR}/_ext/1812479850/pango.o: ../../modules/graphics/src/main/native-font/pango.c 
+	${MKDIR} -p ${OBJECTDIR}/_ext/1812479850
+	${RM} "$@.d"
+	$(COMPILE.c) -O2 -fPIC  -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/_ext/1812479850/pango.o ../../modules/graphics/src/main/native-font/pango.c
+
 # Subprojects
 .build-subprojects:
 
--- a/netbeans/native-font/nbproject/configurations.xml	Wed Apr 23 08:35:01 2014 -0700
+++ b/netbeans/native-font/nbproject/configurations.xml	Thu Apr 24 10:37:43 2014 -0700
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<configurationDescriptor version="89">
+<configurationDescriptor version="94">
   <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
     <logicalFolder name="HeaderFiles"
                    displayName="Header Files"
@@ -19,6 +19,8 @@
         <itemPath>../../modules/graphics/src/main/native-font/directwrite.cpp</itemPath>
         <itemPath>../../modules/graphics/src/main/native-font/fontpath.c</itemPath>
         <itemPath>../../modules/graphics/src/main/native-font/fontpath_linux.c</itemPath>
+        <itemPath>../../modules/graphics/src/main/native-font/freetype.c</itemPath>
+        <itemPath>../../modules/graphics/src/main/native-font/pango.c</itemPath>
       </logicalFolder>
     </logicalFolder>
     <logicalFolder name="TestFiles"
@@ -40,7 +42,6 @@
   <confs>
     <conf name="Debug" type="2">
       <toolsSet>
-        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>default</compilerSet>
         <dependencyChecking>true</dependencyChecking>
         <rebuildPropChanged>false</rebuildPropChanged>
@@ -77,10 +78,19 @@
             tool="0"
             flavor2="0">
       </item>
+      <item path="../../modules/graphics/src/main/native-font/freetype.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+      </item>
+      <item path="../../modules/graphics/src/main/native-font/pango.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+      </item>
     </conf>
     <conf name="Release" type="2">
       <toolsSet>
-        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
         <compilerSet>default</compilerSet>
         <dependencyChecking>true</dependencyChecking>
         <rebuildPropChanged>false</rebuildPropChanged>
@@ -129,6 +139,16 @@
             tool="0"
             flavor2="0">
       </item>
+      <item path="../../modules/graphics/src/main/native-font/freetype.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+      </item>
+      <item path="../../modules/graphics/src/main/native-font/pango.c"
+            ex="false"
+            tool="0"
+            flavor2="0">
+      </item>
     </conf>
   </confs>
 </configurationDescriptor>
--- a/netbeans/native-font/nbproject/project.xml	Wed Apr 23 08:35:01 2014 -0700
+++ b/netbeans/native-font/nbproject/project.xml	Thu Apr 24 10:37:43 2014 -0700
@@ -22,6 +22,9 @@
                     <type>2</type>
                 </confElem>
             </confList>
+            <formatting>
+                <project-formatting-style>false</project-formatting-style>
+            </formatting>
         </data>
     </configuration>
 </project>
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/CreateDeviceTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/CreateDeviceTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -83,14 +83,8 @@
         ui.processLine("EV_SYN");
         TestLog.waitForLog("Key typed: A", 3000);
         // make sure only two key typed events were received
-        String[] log = TestLog.getLog();
-        int typedEvents = 0;
-        for (int i = 0; i < log.length; i++) {
-            if (log[i].startsWith("Key typed")) {
-                typedEvents ++;
-            }
-        }
-        Assert.assertEquals("Expected two typed events", 2, typedEvents);
+        Assert.assertEquals("Expected two typed events", 2,
+                             TestLog.getLog().stream().filter(s -> s.startsWith("Key typed")).count());
     }
 
     @Test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/RotateTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2014, 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
+ * 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
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input;
+
+import com.sun.glass.ui.monocle.input.devices.TestTouchDevice;
+import com.sun.glass.ui.monocle.input.devices.TestTouchDevices;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.runners.Parameterized;
+
+import java.util.Collection;
+
+/**
+ * Rotate tests generated by two touch points.
+ * By default rotation starting form 0 degrees position - on Axis Y,
+ * but it can be sent from any other location on the object
+ *  */
+public class RotateTest extends ParameterizedTestBase {
+
+    private int newX1;
+    private int newY1;
+    private static final int ZERO_ANGLE = 0;
+    private int centerX;
+    private int centerY;
+    private int radius;
+
+    public RotateTest(TestTouchDevice device) {
+        super(device);
+    }
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return TestTouchDevices.getTouchDeviceParameters(2);
+    }
+
+    @Before
+    public void init() {
+        //Rotate tests should be run only on platforms that support current feature
+        Assume.assumeTrue(Boolean.getBoolean("com.sun.javafx.gestures.rotate"));
+        centerX = (int) Math.round(width * 0.5);
+        centerY = (int) Math.round(height * 0.5);
+        radius = (int) Math.round(height * 0.45);
+    }
+
+    private void updateNewTouchPoint(int angle, int radius, int centerX, int centerY) {
+
+        int transformedAngle = 90 - angle;
+        newX1 = centerX + (int) Math.round(radius *
+                Math.cos(Math.toRadians(transformedAngle)));
+        newY1 = centerY - (int) Math.round(radius *
+                Math.sin(Math.toRadians(transformedAngle)));
+    }
+
+    private int getDistance(int xPoint1, int yPoint1, int xPoint2, int yPoint2) {
+        double d = Math.sqrt(Math.pow((xPoint1 - xPoint2), 2)
+                + Math.pow((yPoint1 - yPoint2), 2));
+        return (int) d;
+    }
+
+    private int getRotateThreshold() {
+        String s = System.getProperty("com.sun.javafx.gestures.rotate.threshold");
+        if (s != null) {
+            return Integer.valueOf(s);
+        } else {
+            return 5;
+        }
+    }
+
+    private void Rotate(int startAngle, int radius, int x2, int y2, int angleStep,
+                        int numOfIterations) throws Exception {
+
+        int totalAngle = angleStep;
+        updateNewTouchPoint(startAngle, radius, x2, y2);
+
+        TestLog.reset();
+        int p1 = device.addPoint(newX1, newY1);
+        int p2 = device.addPoint(x2, y2);
+        device.sync();
+        //verify pressing two fingers
+        TestLog.waitForLogContaining("TouchPoint: PRESSED %d, %d", newX1, newY1);
+        TestLog.waitForLogContaining("TouchPoint: PRESSED %d, %d", x2, y2);
+
+        //saving previous coordinates:
+        int previousX = newX1;
+        int previousY = newY1;
+
+        updateNewTouchPoint((angleStep + startAngle), radius, x2, y2);
+
+        Assume.assumeTrue(getDistance(previousX, previousY, newX1, newY1 )
+                > device.getTapRadius());
+
+        //start the rotation
+        TestLog.reset();
+        device.setPoint(p1, newX1, newY1);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: MOVED %d, %d", newX1, newY1);
+        TestLog.waitForLogContaining("TouchPoint: STATIONARY %d, %d", x2, y2);
+
+        if (Math.abs(angleStep) >= getRotateThreshold()) {
+            TestLog.waitForLogContaining("Rotation started, angle: " + ZERO_ANGLE
+                + ", total angle: " + ZERO_ANGLE);
+            TestLog.waitForLogContaining("Rotation, angle: " + angleStep
+                + ", total angle: " + totalAngle);
+        } else {
+            Assert.assertEquals(0, TestLog.countLogContaining("Rotation started"));
+            Assert.assertEquals(0, TestLog.countLogContaining("Rotation, angle"));
+        }
+        boolean passedTheThreshold =false;
+        if (numOfIterations >= 2) {
+            for (int i = 2; i <= numOfIterations; i++) {
+                updateNewTouchPoint(angleStep * i + startAngle, radius, x2, y2);
+                totalAngle += angleStep;
+                TestLog.reset();
+                device.setPoint(p1, newX1, newY1);
+                device.sync();
+
+                TestLog.waitForLogContaining("TouchPoint: MOVED %d, %d", newX1, newY1);
+                TestLog.waitForLogContaining("TouchPoint: STATIONARY %d, %d", x2, y2);
+
+                String expectedLog;
+                if (Math.abs(angleStep) < getRotateThreshold()) {
+                    if(Math.abs(totalAngle) >= getRotateThreshold()) {
+                        if (!passedTheThreshold) {
+                            expectedLog = "Rotation, angle: " + totalAngle
+                                + ", total angle: " + totalAngle;
+                            passedTheThreshold = true;
+                        } else {
+                            expectedLog = "Rotation, angle: " + angleStep
+                                + ", total angle: " + totalAngle;
+                        }
+                    } else {
+                        expectedLog = "sync";
+                    }
+                } else {
+                    expectedLog = "Rotation, angle: " + angleStep
+                            + ", total angle: " + totalAngle;
+                }
+                TestLog.waitForLogContaining(expectedLog);
+            }
+        }
+        TestLog.reset();
+        device.removePoint(p1);
+        device.removePoint(p2);
+        device.sync();
+        //verify fingers release
+        TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", newX1, newY1);
+        TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x2, y2);
+        if (Math.abs(totalAngle) >= getRotateThreshold()) {
+            TestLog.waitForLogContaining("Rotation finished, angle: "
+                    + ZERO_ANGLE + ", total angle: " + totalAngle);
+            Assert.assertEquals(1, TestLog.countLogContaining("Rotation " +
+                    "finished, "
+                    + "angle: " + ZERO_ANGLE + ", total angle: " + totalAngle));
+        } else {
+            Assert.assertEquals(0, TestLog.countLogContaining("Rotation finished, "
+                    + "angle: " + ZERO_ANGLE + ", total angle: " + totalAngle));
+        }
+    }
+
+    private void Rotate(int radius, int x2, int y2, int angleStep,
+                        int numOfIterations) throws Exception {
+        Rotate(0, radius, x2, y2, angleStep, numOfIterations);
+    }
+
+    private void Rotate(int startAngle, int angleStep, int numOfIterations) throws Exception {
+        Rotate(startAngle, radius, centerX, centerY, angleStep, numOfIterations);
+    }
+
+    private void Rotate(int angleStep, int numOfIterations) throws Exception {
+        Rotate(0, radius, centerX, centerY, angleStep, numOfIterations);
+    }
+
+    /**
+     * Tap two fingers, drag a little bit upper finger right in order move,
+     * but not enough for rotation.
+     */
+    @Test
+    public void testSmallStepRightNoRotateSent() throws Exception {
+        Rotate(4, 1);
+    }
+
+    /**
+     * Tap two fingers, drag a little bit upper finger right in order move,
+     * but not enough for rotation, then make 2 more small moves
+     */
+    @Test
+    public void testRotateRightByFewSmallSteps() throws Exception {
+        Rotate(4, 5);
+    }
+
+    /**
+     * Tap two fingers, drag upper finger right in order to rotate
+     */
+    @Test
+    public void testRotateRight() throws Exception {
+        Rotate(15, 6);
+    }
+
+    /**
+     * Tap two fingers, rotate the object right (by 3 steps, 50 degrees each)
+     */
+    @Test
+    public void testRotateRightBigSteps() throws Exception {
+        Rotate(50, 3);
+    }
+
+    /**
+     * Tap two fingers, rotate the object right by only 1 very big step - 80 degrees
+     */
+    @Test
+    @Ignore //RT-36616
+    public void testRotateRightOneBigStep() throws Exception {
+        Rotate(80, 1);
+    }
+
+    /**
+     * Tap two fingers, drag a little bit upper finger left in order move,
+     * but not enough for rotation.
+     */
+    @Test
+    public void testSmallStepLeftNoRotateSent() throws Exception {
+        Rotate(-4, 1);
+    }
+
+    /**
+     * Tap two fingers, drag a little bit upper finger left in order move,
+     * but not enough for rotation, then make 9 more small moves
+     */
+    @Test
+    public void testRotateLeftByFewSmallSteps() throws Exception {
+        Rotate(-4, 10);
+    }
+
+    /**
+     * Tap two fingers, drag upper finger left in order to rotate
+     */
+    @Test
+    public void testRotateLeft() throws Exception {
+        Rotate(-10, 4);
+    }
+
+    /**
+     * Tap two fingers, rotate the object left (by 5 steps, 40 degrees each)
+     */
+    @Test
+    public void testRotateLeftBigSteps() throws Exception {
+        Rotate(-40, 5);
+    }
+
+    /**
+     * Tap two fingers, rotate the object left by only 1 very big step - 70 degrees
+     */
+    @Test
+    @Ignore //RT-36616
+    public void testRotateLeftOneBigStep() throws Exception {
+        Rotate(-70, 1);
+    }
+
+    /**
+     * Tap two fingers in 45 degrees, rotate the object right
+     */
+    @Test
+    public void testRotateRightFrom45Degrees() throws Exception {
+        Rotate(45, 20, 3);
+    }
+
+    /**
+     * Tap two fingers in 45 degrees, rotate the object left
+     */
+    @Test
+    public void testRotateLeftFrom45Degrees() throws Exception {
+        Rotate(45, -20, 3);
+    }
+
+    /**
+     * Tap two fingers in -45 degrees, rotate the object right
+     */
+    @Test
+    public void testRotateRightFromMinus45Degrees() throws Exception {
+        Rotate(-45, 20, 3);
+    }
+
+    /**
+     * Tap two fingers in -45 degrees, rotate the object left
+     */
+    @Test
+    public void testRotateLeftFromMinus45Degrees() throws Exception {
+        Rotate(-45, -20, 3);
+    }
+
+    /**
+     * Tap two fingers in 140 degrees, rotate the object right
+     */
+    @Test
+    public void testRotateRightFrom140Degrees() throws Exception {
+        Rotate(140, 20, 3);
+    }
+
+    /**
+     * Tap two fingers in 140 degrees, rotate the object left
+     */
+    @Test
+    public void testRotateLeftFrom140Degrees() throws Exception {
+        Rotate(140, -20, 3);
+    }
+
+    /**
+     * Tap two fingers in -140 degrees, rotate the object right
+     */
+    @Test
+    public void testRotateRightFromMinus140Degrees() throws Exception {
+        Rotate(-140, 20, 3);
+    }
+
+    /**
+     * Tap two fingers in -140 degrees, rotate the object left
+     */
+    @Test
+    public void testRotateLeftFromMinus140Degrees() throws Exception {
+        Rotate(-140, -20, 3);
+    }
+
+}
\ No newline at end of file
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SimpleMouseTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SimpleMouseTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -25,7 +25,11 @@
 
 package com.sun.glass.ui.monocle.input;
 
+import javafx.geometry.Rectangle2D;
+import javafx.stage.Screen;
 import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -112,4 +116,125 @@
         TestLog.waitForLog("Scroll: -1");
     }
 
+    @Test
+    public void testClickLeft() throws Exception {
+        ui.processLine("EV_KEY BTN_LEFT 1");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        ui.processLine("EV_KEY BTN_LEFT 0");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        TestLog.waitForLogContaining("Mouse pressed: 300, 300");
+        TestLog.waitForLogContaining("Mouse released: 300, 300");
+        TestLog.waitForLogContaining("Mouse clicked: 300, 300");
+    }
+
+    @Test
+    public void testClickRight() throws Exception {
+        ui.processLine("EV_KEY BTN_RIGHT 1");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        ui.processLine("EV_KEY BTN_RIGHT 0");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        TestLog.waitForLogContaining("Mouse pressed: 300, 300");
+        TestLog.waitForLogContaining("Mouse released: 300, 300");
+        TestLog.waitForLogContaining("Mouse clicked: 300, 300");
+    }
+
+    @Test
+    public void testDragLookahead() throws Exception {
+        Assume.assumeTrue(TestApplication.isMonocle());
+        TestApplication.showFullScreenScene();
+        TestApplication.addMouseListeners();
+        TestLog.reset();
+        Rectangle2D r = Screen.getPrimary().getBounds();
+        final int width = (int) r.getWidth();
+        final int height = (int) r.getHeight();
+        final int x1 = (int) Math.round(width * 0.1);
+        final int y1 = (int) Math.round(height * 0.1);
+        final int delta = (int) Math.min(width / 2.0, height / 2.0);
+        final int x2 = x1 + delta;
+        final int y2 = y1 + delta;
+        final int x3 = (int) Math.round(width * 0.9);
+        final int y3 = (int) Math.round(height * 0.9);
+        // Move the mouse to 0, 0
+        ui.processLine("EV_REL REL_X " + -width);
+        ui.processLine("EV_REL REL_Y " + -height);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: 0, 0");
+        // Move to x1, y1
+        ui.processLine("EV_REL REL_X " + x1);
+        ui.processLine("EV_REL REL_Y " + y1);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: %d, %d", x1, y1);
+        // Push events while on the event thread, making sure that events
+        // will be buffered up and enabling filtering to take place
+        TestRunnable.invokeAndWait(() -> {
+            ui.processLine("EV_KEY BTN_LEFT 1");
+            ui.processLine("EV_SYN");
+            for (int i = 0; i < delta; i++) {
+                ui.processLine("EV_REL REL_X 1");
+                ui.processLine("EV_REL REL_Y 1");
+                ui.processLine("EV_SYN");
+            }
+            ui.processLine("EV_REL REL_X " + (x3 - x2));
+            ui.processLine("EV_REL REL_Y " + (y3 - y2));
+            ui.processLine("EV_SYN");
+            ui.processLine("EV_KEY BTN_LEFT 0");
+            ui.processLine("EV_SYN");
+        });
+        // Check that the initial point reported is correct
+        TestLog.waitForLog("Mouse pressed: %d, %d", x1, y1);
+        // Check that the final point reported is correct
+        TestLog.waitForLog("Mouse released: %d, %d", x3, y3);
+        TestLog.waitForLog("Mouse dragged: %d, %d", x3, y3);
+        // Check that moves in between were filtered
+        Assert.assertTrue(TestLog.countLogContaining("Mouse dragged") <= (x2 - x1) / 10);
+    }
+
+    @Test
+    public void testMoveLookahead() throws Exception {
+        Assume.assumeTrue(TestApplication.isMonocle());
+        TestApplication.showFullScreenScene();
+        TestApplication.addMouseListeners();
+        TestLog.reset();
+        Rectangle2D r = Screen.getPrimary().getBounds();
+        final int width = (int) r.getWidth();
+        final int height = (int) r.getHeight();
+        final int x1 = (int) Math.round(width * 0.1);
+        final int y1 = (int) Math.round(height * 0.1);
+        final int delta = (int) Math.min(width / 2.0, height / 2.0);
+        final int x2 = x1 + delta;
+        final int y2 = y1 + delta;
+        final int x3 = (int) Math.round(width * 0.9);
+        final int y3 = (int) Math.round(height * 0.9);
+        // Move the mouse to 0, 0
+        ui.processLine("EV_REL REL_X " + -width);
+        ui.processLine("EV_REL REL_Y " + -height);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: 0, 0");
+        // Move to x1, y1
+        ui.processLine("EV_REL REL_X " + x1);
+        ui.processLine("EV_REL REL_Y " + y1);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: %d, %d", x1, y1);
+        // Push events while on the event thread, making sure that events
+        // will be buffered up and enabling filtering to take place
+        TestRunnable.invokeAndWait(() -> {
+            for (int i = 0; i < delta; i++) {
+                ui.processLine("EV_REL REL_X 1");
+                ui.processLine("EV_REL REL_Y 1");
+                ui.processLine("EV_SYN");
+            }
+            ui.processLine("EV_REL REL_X " + (x3 - x2));
+            ui.processLine("EV_REL REL_Y " + (y3 - y2));
+            ui.processLine("EV_SYN");
+        });
+        // Check that the final point reported is correct
+        TestLog.waitForLog("Mouse moved: %d, %d", x3, y3);
+        // Check that moves in between were filtered
+        Assert.assertTrue(TestLog.countLogContaining("Mouse moved") <= (x2 - x1) / 10);
+        // Check that we didn't get any other events
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse pressed"));
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse released"));
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse clicked"));
+    }
+
 }
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SingleTouchTest.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SingleTouchTest.java	Thu Apr 24 10:37:43 2014 -0700
@@ -63,6 +63,12 @@
         TestLog.waitForLog("Mouse clicked: %d, %d", x, y);
         TestLog.waitForLog("Touch pressed: %d, %d", x, y);
         TestLog.waitForLog("Touch released: %d, %d", x, y);
+
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
     /**
@@ -91,6 +97,11 @@
         // same location, so make sure they are filtered out.
         Assert.assertEquals(0, TestLog.countLogContaining("Mouse pressed:"));
         Assert.assertEquals(0, TestLog.countLogContaining("Touch pressed:"));
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
     /**
@@ -118,6 +129,11 @@
         TestLog.waitForLog("Touch pressed: %d, %d", x1, y1);
         TestLog.waitForLog("Touch moved: %d, %d", x2, y2);
         TestLog.waitForLog("Touch released: %d, %d", x2, y2);
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
     /**
@@ -144,6 +160,11 @@
         TestLog.waitForLog("Touch pressed: %d, %d", x1, y1);
         TestLog.waitForLog("Touch moved: %d, %d", x2, y1);
         TestLog.waitForLog("Touch released: %d, %d", x2, y1);
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
     /**
@@ -170,6 +191,11 @@
         TestLog.waitForLog("Touch pressed: %d, %d", x1, y1);
         TestLog.waitForLog("Touch moved: %d, %d", x1, y2);
         TestLog.waitForLog("Touch released: %d, %d", x1, y2);
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
     /**
@@ -198,6 +224,11 @@
         TestLog.waitForLog("Touch released: %d, %d", x1, y1);
         Assert.assertEquals(0l, TestLog.countLogContaining("Mouse dragged"));
         Assert.assertEquals(0l, TestLog.countLogContaining("Touch moved"));
+        // Check that the touch event has one touch point.
+        Assert.assertEquals("Expected only one touch point", 0,
+                            TestLog.getLog().stream()
+                            .filter(s -> s.startsWith("Touch point count"))
+                            .filter(s -> !s.startsWith("Touch point count: 1")).count());
     }
 
 
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/TestApplication.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/TestApplication.java	Thu Apr 24 10:37:43 2014 -0700
@@ -231,6 +231,7 @@
 
     public static void addTouchListeners() throws Exception {
         Consumer<List<TouchPoint>> logTouchPoints = (tps) -> {
+            TestLog.log("Touch points count: [" + tps.size() +"]"); 
             for (TouchPoint tp : tps) {
                 TestLog.log("TouchPoint: " + tp.getState() + " "
                         + (int) tp.getScreenX() + ", " + (int) tp.getScreenY()
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/TestLog.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/TestLog.java	Thu Apr 24 10:37:43 2014 -0700
@@ -55,8 +55,8 @@
         log(new Formatter().format(format, args).toString());
     }
 
-    public static String[] getLog() {
-        return log.toArray(new String[log.size()]);
+    public static  List<String> getLog() {
+        return new ArrayList<>(log);
     }
 
     public static void clear() {
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxSingleTouchDevice.java	Wed Apr 23 08:35:01 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2014, 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
- * 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
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.glass.ui.monocle.input.devices;
-
-import com.sun.glass.ui.monocle.input.TestApplication;
-import com.sun.glass.ui.monocle.input.UInput;
-import org.junit.Assume;
-
-/**
- * EGalaxSingleTouchDevice sends ABS_X and ABS_Y events. It uses BTN_TOUCH to notify
- * presses and releases. It does not send ABS_X or ABS_Y if that coordinate has
- * not changed. Before the first touch it sends coordinates with no EV_KEY
- * event.
- */
-public class EGalaxSingleTouchDevice extends TestTouchDevice {
-
-    private boolean firstPress = true;
-
-    public EGalaxSingleTouchDevice() {
-        super(1);
-    }
-
-    @Override
-    public void create() {
-        Assume.assumeTrue(TestApplication.isMonocle());
-        ui = new UInput();
-        ui.processLine("OPEN");
-        ui.processLine("EVBIT EV_SYN");
-        ui.processLine("EVBIT EV_KEY");
-        ui.processLine("KEYBIT BTN_TOUCH");
-        ui.processLine("EVBIT EV_ABS");
-        ui.processLine("ABSBIT ABS_X");
-        ui.processLine("ABSBIT ABS_Y");
-        ui.processLine("ABSMIN ABS_X 0");
-        ui.processLine("ABSMAX ABS_X 4095");
-        ui.processLine("ABSMIN ABS_Y 0");
-        ui.processLine("ABSMAX ABS_Y 4095");
-        ui.processLine("PROPBIT INPUT_PROP_POINTER");
-        ui.processLine("PROPBIT INPUT_PROP_DIRECT");
-        ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
-        ui.processLine("CREATE");
-        setAbsScale(4096, 4096);
-    }
-
-    @Override
-    public int addPoint(double x, double y) {
-        int p = super.addPoint(x, y);
-        if (firstPress) {
-            ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
-            ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
-            ui.processLine("EV_SYN SYN_REPORT 0");
-            firstPress = false;
-        }
-        ui.processLine("EV_KEY BTN_TOUCH 1");
-        ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
-        ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
-        return p;
-    }
-
-    @Override
-    public void removePoint(int p) {
-        super.removePoint(p);
-        ui.processLine("EV_KEY BTN_TOUCH 0");
-    }
-
-    @Override
-    public void setPoint(int p, double x, double y) {
-        int oldX = transformedXs[p];
-        int oldY = transformedYs[p];
-        super.setPoint(p, x, y);
-        // if neither X nor Y have changed, we send X
-        if (oldX != transformedXs[p] || oldY == transformedYs[p]) {
-            ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
-        }
-        if (oldY != transformedYs[p]) {
-            ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
-        }
-    }
-
-    @Override
-    public void resendStateAndSync() {
-        if (points[0]) {
-            ui.processLine("EV_ABS ABS_X " + transformedXs[0]);
-            ui.processLine("EV_ABS ABS_Y " + transformedYs[0]);
-        }
-        sync();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxSingleTouchDevice1.java	Thu Apr 24 10:37:43 2014 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 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
+ * 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
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+import com.sun.glass.ui.monocle.input.TestApplication;
+import com.sun.glass.ui.monocle.input.UInput;
+import org.junit.Assume;
+
+
+public class EGalaxSingleTouchDevice1 extends EGalaxSingleTouchDeviceBase {
+
+    private boolean firstPress = true;
+
+    @Override
+    public int addPoint(double x, double y) {
+        int p = super.addPoint(x, y);
+        if (firstPress) {
+            ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
+            ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
+            ui.processLine("EV_SYN SYN_REPORT 0");
+            firstPress = false;
+        }
+        ui.processLine("EV_KEY BTN_TOUCH 1");
+        ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
+        ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
+        return p;
+    }
+
+    @Override
+    public void removePoint(int p) {
+        super.removePoint(p);
+        ui.processLine("EV_KEY BTN_TOUCH 0");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxSingleTouchDevice2.java	Thu Apr 24 10:37:43 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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
+ * 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
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+import com.sun.glass.ui.monocle.input.TestApplication;
+import com.sun.glass.ui.monocle.input.UInput;
+import org.junit.Assume;
+
+public class EGalaxSingleTouchDevice2 extends EGalaxSingleTouchDeviceBase {
+
+    @Override
+    public int addPoint(double x, double y) {
+        int p = super.addPoint(x, y);
+        ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
+        ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
+        ui.processLine("EV_KEY BTN_TOUCH 1");
+        ui.processLine("EV_ABS ABS_PRESSURE 1");
+        return p;
+    }
+
+    @Override
+    public void removePoint(int p) {
+        super.removePoint(p);
+        ui.processLine("EV_KEY BTN_TOUCH 0");
+        ui.processLine("EV_ABS ABS_PRESSURE 0");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxSingleTouchDeviceBase.java	Thu Apr 24 10:37:43 2014 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, 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
+ * 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
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+import com.sun.glass.ui.monocle.input.TestApplication;
+import com.sun.glass.ui.monocle.input.UInput;
+import org.junit.Assume;
+
+/**
+ * EGalaxSingleTouchDeviceBase sends ABS_X and ABS_Y events. It uses BTN_TOUCH to notify
+ * presses and releases. It does not send ABS_X or ABS_Y if that coordinate has
+ * not changed. Before the first touch it sends coordinates with no EV_KEY
+ * event.
+ */
+public abstract class EGalaxSingleTouchDeviceBase extends TestTouchDevice {
+
+    public EGalaxSingleTouchDeviceBase() {
+        super(1);
+    }
+
+    @Override
+    public void create() {
+        Assume.assumeTrue(TestApplication.isMonocle());
+        ui = new UInput();
+        ui.processLine("OPEN");
+        ui.processLine("EVBIT EV_SYN");
+        ui.processLine("EVBIT EV_KEY");
+        ui.processLine("KEYBIT BTN_TOUCH");
+        ui.processLine("EVBIT EV_ABS");
+        ui.processLine("ABSBIT ABS_X");
+        ui.processLine("ABSBIT ABS_Y");
+        ui.processLine("ABSMIN ABS_X 0");
+        ui.processLine("ABSMAX ABS_X 4095");
+        ui.processLine("ABSMIN ABS_Y 0");
+        ui.processLine("ABSMAX ABS_Y 4095");
+        ui.processLine("PROPBIT INPUT_PROP_POINTER");
+        ui.processLine("PROPBIT INPUT_PROP_DIRECT");
+        ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
+        ui.processLine("CREATE");
+        setAbsScale(4096, 4096);
+    }
+
+    @Override
+    public void setPoint(int p, double x, double y) {
+        int oldX = transformedXs[p];
+        int oldY = transformedYs[p];
+        super.setPoint(p, x, y);
+        // if neither X nor Y have changed, we send X
+        if (oldX != transformedXs[p] || oldY == transformedYs[p]) {
+            ui.processLine("EV_ABS ABS_X " + transformedXs[p]);
+        }
+        if (oldY != transformedYs[p]) {
+            ui.processLine("EV_ABS ABS_Y " + transformedYs[p]);
+        }
+    }
+
+    @Override
+    public void resendStateAndSync() {
+        if (points[0]) {
+            ui.processLine("EV_ABS ABS_X " + transformedXs[0]);
+            ui.processLine("EV_ABS ABS_Y " + transformedYs[0]);
+        }
+        sync();
+    }
+
+}
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/TestTouchDevices.java	Wed Apr 23 08:35:01 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/TestTouchDevices.java	Thu Apr 24 10:37:43 2014 -0700
@@ -60,7 +60,8 @@
         devices.addAll(Arrays.asList(new TestTouchDevice[] {
                 new SingleTouchDevice1(),
                 new SingleTouchDevice2(),
-                new EGalaxSingleTouchDevice(),
+                new EGalaxSingleTouchDevice1(),
+                new EGalaxSingleTouchDevice2(),
                 new EGalaxMultiTouchDevice1(),
                 new EGalaxMultiTouchDevice2(),
                 new TouchRevolutionFusionDevice(),