modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ComboBoxPopupControl.java

Print this page
rev 9038 : RT-34620: [ComboBox, DatePicker] Buttons set to default/cancel are not reacting to ComboBox enter/esc keys

@@ -87,16 +87,28 @@
                 // This prevents a stack overflow from our rebroadcasting of the
                 // event to the textfield that occurs in the final else statement
                 // of the conditions below.
                 if (ke.getTarget().equals(textField)) return;
 
+                switch (ke.getCode()) {
+                  case ESCAPE:
+                  case F10:
+                      // Allow to bubble up.
+                      break;
+
+                  case ENTER:
+                    handleKeyEvent(ke, true);
+                    break;
+
+                  default:
                 // Fix for the regression noted in a comment in RT-29885.
                 // This forwards the event down into the TextField when
                 // the key event is actually received by the ComboBox.
                 textField.fireEvent(ke.copyFor(textField, textField));
                 ke.consume();
             }
+            }
         });
 
         // RT-38978: Forward input method events to TextField if editable.
         if (comboBoxBase.getOnInputMethodTextChanged() == null) {
             comboBoxBase.setOnInputMethodTextChanged(event -> {

@@ -315,15 +327,10 @@
      *                                                                         *
      * TextField Listeners                                                     *
      *                                                                         *
      **************************************************************************/
     
-    private EventHandler<KeyEvent> textFieldKeyEventHandler = event -> {
-        if (getEditor() != null && textField != null) {
-            handleKeyEvent(event, true);
-        }
-    };
     private EventHandler<MouseEvent> textFieldMouseEventHandler = event -> {
         ComboBoxBase<T> comboBoxBase = getSkinnable();
         if (!event.getTarget().equals(comboBoxBase)) {
             comboBoxBase.fireEvent(event.copyFor(comboBoxBase, comboBoxBase));
             event.consume();

@@ -355,32 +362,17 @@
 
     private String initialTextFieldValue = null;
     protected TextField getEditableInputNode() {
         if (textField == null && getEditor() != null) {
             textField = getEditor();
-            textField.focusTraversableProperty().bindBidirectional(comboBoxBase.focusTraversableProperty());
+            textField.setFocusTraversable(false);
             textField.promptTextProperty().bind(comboBoxBase.promptTextProperty());
             textField.tooltipProperty().bind(comboBoxBase.tooltipProperty());
 
             // Fix for RT-21406: ComboBox do not show initial text value
             initialTextFieldValue = textField.getText();
             // End of fix (see updateDisplayNode below for the related code)
-
-            textField.focusedProperty().addListener((ov, t, hasFocus) -> {
-                if (getEditor() != null) {
-                    // Fix for RT-29885
-                    comboBoxBase.getProperties().put("FOCUSED", hasFocus);
-                    // --- end of RT-29885
-
-                    // RT-21454 starts here
-                    if (!hasFocus) {
-                        setTextFromTextFieldIntoComboBoxValue();
-                    }
-                    pseudoClassStateChanged(CONTAINS_FOCUS_PSEUDOCLASS_STATE, hasFocus);
-                    // --- end of RT-21454
-                }
-            });
         }
 
         return textField;
     }
 

@@ -439,43 +431,43 @@
         // When the user hits the enter or F4 keys, we respond before
         // ever giving the event to the TextField.
         if (ke.getCode() == KeyCode.ENTER) {
             setTextFromTextFieldIntoComboBoxValue();
 
-            if (doConsume) ke.consume();
+            if (doConsume && comboBoxBase.getOnAction() != null) {
+                ke.consume();
+            } else {
+                forwardToParent(ke);
+            }
         } else if (ke.getCode() == KeyCode.F4) {
             if (ke.getEventType() == KeyEvent.KEY_RELEASED) {
                 if (comboBoxBase.isShowing()) comboBoxBase.hide();
                 else comboBoxBase.show();
             }
             ke.consume(); // we always do a consume here (otherwise unit tests fail)
-        } else if (ke.getCode() == KeyCode.F10 || ke.getCode() == KeyCode.ESCAPE) {
-            // RT-23275: The TextField fires F10 and ESCAPE key events
-            // up to the parent, which are then fired back at the
-            // TextField, and this ends up in an infinite loop until
-            // the stack overflows. So, here we consume these two
-            // events and stop them from going any further.
-            if (doConsume) ke.consume();
         }
     }
 
+    private void forwardToParent(KeyEvent event) {
+        if (comboBoxBase.getParent() != null) {
+            comboBoxBase.getParent().fireEvent(event);
+        }
+    }
 
     protected void updateEditable() {
         TextField newTextField = getEditor();
 
         if (getEditor() == null) {
             // remove event filters
             if (textField != null) {
-                textField.removeEventFilter(KeyEvent.ANY, textFieldKeyEventHandler);
                 textField.removeEventFilter(MouseEvent.DRAG_DETECTED, textFieldMouseEventHandler);
                 textField.removeEventFilter(DragEvent.ANY, textFieldDragEventHandler);
 
                 comboBoxBase.setInputMethodRequests(null);
             }
         } 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);

@@ -521,10 +513,16 @@
      *                                                                         *
      **************************************************************************/
 
     public static final class FakeFocusTextField extends TextField {
 
+        @Override public void requestFocus() {
+            if (getParent() != null) {
+                getParent().requestFocus();
+            }
+        }
+
         public void setFakeFocus(boolean b) {
             setFocused(b);
         }
 
         @Override