Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8242167: ios keyboard handling
Reviewed-by: kcr
  • Loading branch information
Johan Vos committed Apr 7, 2020
1 parent 844460b commit fda015c
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 79 deletions.
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020, 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 javafx.scene.control.skin;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextArea;
import javafx.scene.control.skin.TextAreaSkin;

public class TextAreaSkinIos extends TextAreaSkin {

public TextAreaSkinIos(final TextArea textArea) {
super(textArea);

textArea.focusedProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observable,
Boolean wasFocused, Boolean isFocused) {
if (textArea.isEditable()) {
if (isFocused) {
showSoftwareKeyboard();
} else {
hideSoftwareKeyboard();
}
}
}
});
}

native void showSoftwareKeyboard();
native void hideSoftwareKeyboard();

}
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2020, 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 javafx.scene.control.skin;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;

import com.sun.javafx.scene.control.behavior.TextFieldBehavior;
import javafx.scene.control.skin.TextFieldSkin;

public class TextFieldSkinIos extends TextFieldSkin {

public TextFieldSkinIos(final TextField textField) {
super(textField);

textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observable,
Boolean wasFocused, Boolean isFocused) {
if (textField.isEditable()) {
if (isFocused) {
showSoftwareKeyboard();
} else {
hideSoftwareKeyboard();
}
}
}
});
}

native void showSoftwareKeyboard();
native void hideSoftwareKeyboard();

}
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2020, 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.
*/

/*******************************************************************************
* *
* Ios specific css *
* *
******************************************************************************/


/*******************************************************************************
* *
* TextField *
* *
******************************************************************************/

.text-field {
-fx-skin: "javafx.scene.control.skin.TextFieldSkinIos";
}


/*******************************************************************************
* *
* TextArea *
* *
******************************************************************************/

.text-area {
-fx-skin: "javafx.scene.control.skin.TextAreaSkinIos";
}

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2020, 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.
*/

/*******************************************************************************
* *
* Ios specific css *
* *
******************************************************************************/


/*******************************************************************************
* *
* TextField *
* *
******************************************************************************/

.text-field {
-fx-skin: "javafx.scene.control.skin.TextFieldSkinIos";
}


/*******************************************************************************
* *
* TextArea *
* *
******************************************************************************/

.text-area {
-fx-skin: "javafx.scene.control.skin.TextAreaSkinIos";
}

Expand Up @@ -149,33 +149,11 @@ public void changed(ObservableValue<? extends Boolean> observable, Boolean oldVa
// TextArea doesn't lose selection on focus lost, whereas the TextField does.
final TextArea textArea = getNode();
if (textArea.isFocused()) {
if (PlatformUtil.isIOS()) {
// Special handling of focus on iOS is required to allow to
// control native keyboard, because native keyboard is popped-up only when native
// text component gets focus. When we have JFX keyboard we can remove this code
final Bounds bounds = textArea.getBoundsInParent();
double w = bounds.getWidth();
double h = bounds.getHeight();
Affine3D trans = TextFieldBehavior.calculateNodeToSceneTransform(textArea);
String text = textArea.textProperty().getValueSafe();

// we need to display native text input component on the place where JFX component is drawn
// all parameters needed to do that are passed to native impl. here
WindowHelper.getPeer(textArea.getScene().getWindow()).requestInput(
text, TextFieldBehavior.TextInputTypes.TEXT_AREA.ordinal(), w, h,
trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),
trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),
trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
}
if (!focusGainedByMouseClick) {
setCaretAnimating(true);
}
} else {
// skin.hideCaret();
if (PlatformUtil.isIOS() && textArea.getScene() != null) {
// releasing the focus => we need to hide the native component and also native keyboard
WindowHelper.getPeer(textArea.getScene().getWindow()).releaseInput();
}
focusGainedByMouseClick = false;
setCaretAnimating(false);
}
Expand Down
Expand Up @@ -120,41 +120,10 @@ private void handleFocusChange() {
TextField textField = getNode();

if (textField.isFocused()) {
if (PlatformUtil.isIOS()) {
// special handling of focus on iOS is required to allow to
// control native keyboard, because nat. keyboard is poped-up only when native
// text component gets focus. When we have JFX keyboard we can remove this code
TextInputTypes type = TextInputTypes.TEXT_FIELD;
if (textField.getClass().equals(javafx.scene.control.PasswordField.class)) {
type = TextInputTypes.PASSWORD_FIELD;
} else if (textField.getParent().getClass().equals(javafx.scene.control.ComboBox.class)) {
type = TextInputTypes.EDITABLE_COMBO;
}
final Bounds bounds = textField.getBoundsInParent();
double w = bounds.getWidth();
double h = bounds.getHeight();
Affine3D trans = calculateNodeToSceneTransform(textField);
// Insets insets = skin.getInsets();
// w -= insets.getLeft() + insets.getRight();
// h -= insets.getTop() + insets.getBottom();
String text = textField.getText();

// we need to display native text input component on the place where JFX component is drawn
// all parameters needed to do that are passed to native impl. here
WindowHelper.getPeer(textField.getScene().getWindow()).requestInput(
text, type.ordinal(), w, h,
trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),// + insets.getLeft(),
trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),// + insets.getTop(),
trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
}
if (!focusGainedByMouseClick) {
setCaretAnimating(true);
}
} else {
if (PlatformUtil.isIOS() && textField.getScene() != null) {
// releasing the focus => we need to hide the native component and also native keyboard
WindowHelper.getPeer(textField.getScene().getWindow()).releaseInput();
}
focusGainedByMouseClick = false;
setCaretAnimating(false);
}
Expand Down
Expand Up @@ -687,12 +687,6 @@ protected void handleInputMethodEvent(InputMethodEvent event) {
final TextInputControl textInput = getSkinnable();
if (textInput.isEditable() && !textInput.textProperty().isBound() && !textInput.isDisabled()) {

// just replace the text on iOS
if (PlatformUtil.isIOS()) {
textInput.setText(event.getCommitted());
return;
}

// remove previous input method text (if any) or selected text
if (imlength != 0) {
removeHighlight(imattrs);
Expand Down
Expand Up @@ -787,6 +787,9 @@ private static void _setPlatformUserAgentStylesheet(String stylesheetUrl) {
if (PlatformUtil.isAndroid()) {
uaStylesheets.add("com/sun/javafx/scene/control/skin/caspian/android.css");
}
if (PlatformUtil.isIOS()) {
uaStylesheets.add("com/sun/javafx/scene/control/skin/caspian/ios.css");
}
}

if (isSupported(ConditionalFeature.TWO_LEVEL_FOCUS)) {
Expand Down Expand Up @@ -816,6 +819,9 @@ private static void _setPlatformUserAgentStylesheet(String stylesheetUrl) {
if (PlatformUtil.isAndroid()) {
uaStylesheets.add("com/sun/javafx/scene/control/skin/modena/android.css");
}
if (PlatformUtil.isIOS()) {
uaStylesheets.add("com/sun/javafx/scene/control/skin/modena/ios.css");
}

if (isSupported(ConditionalFeature.TWO_LEVEL_FOCUS)) {
uaStylesheets.add("com/sun/javafx/scene/control/skin/modena/two-level-focus.css");
Expand Down
Expand Up @@ -52,5 +52,7 @@
UIView *inputAccessoryView;
UIView *nativeView; // view used for user input
}
-(void) doInsertText:(NSString*)myText;
-(void) doDeleteBackward;

@end
13 changes: 13 additions & 0 deletions modules/javafx.graphics/src/main/native-glass/ios/GlassViewGL.m
Expand Up @@ -124,6 +124,19 @@ - (void)dealloc {

@implementation GlassViewGL : GLView

-(void) doInsertText:(NSString*)myText {
int asciiCode = [myText characterAtIndex:0];
[self->delegate sendJavaKeyEventWithType:111 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
[self->delegate sendJavaKeyEventWithType:113 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
[self->delegate sendJavaKeyEventWithType:112 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
}

-(void) doDeleteBackward {
int asciiCode = 8;
[self->delegate sendJavaKeyEventWithType:111 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
[self->delegate sendJavaKeyEventWithType:113 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
[self->delegate sendJavaKeyEventWithType:112 keyCode:asciiCode chars:(char)asciiCode modifiers:0];
}

-(BOOL) touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
Expand Down
Expand Up @@ -40,7 +40,7 @@

@end

@interface GlassWindow : UIView
@interface GlassWindow : UIView<UIKeyInput>
{
jobject jWindow; // Glass java Window object

Expand Down

0 comments on commit fda015c

Please sign in to comment.