Skip to content

Commit

Permalink
iOS: fix keyboard display.
Browse files Browse the repository at this point in the history
Fixes keyboard display for non-english keyboards.
Fixes multiple character insert.
  • Loading branch information
naithar committed Nov 6, 2020
1 parent 150f9ce commit 74d5be7
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 41 deletions.
1 change: 1 addition & 0 deletions platform/iphone/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ iphone_lib = [
"godot_view_renderer.mm",
"godot_view_gesture_recognizer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
"native_video_view.m",
]

Expand Down
4 changes: 1 addition & 3 deletions platform/iphone/godot_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class String;
@protocol DisplayLayer;
@protocol GodotViewRendererProtocol;

@interface GodotView : UIView <UIKeyInput>
@interface GodotView : UIView

@property(assign, nonatomic) id<GodotViewRendererProtocol> renderer;

Expand All @@ -55,8 +55,6 @@ class String;
- (void)stopRendering;
- (void)startRendering;

- (BOOL)becomeFirstResponderWithString:(String)p_existing;

@property(nonatomic, assign) BOOL useCADisplayLink;

@end
35 changes: 0 additions & 35 deletions platform/iphone/godot_view.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

#import "godot_view.h"

#include "core/os/keyboard.h"
#include "core/project_settings.h"
#include "os_iphone.h"
#include "servers/audio_server.h"
Expand Down Expand Up @@ -275,40 +274,6 @@ - (void)layoutSubviews {

// MARK: - Input

// MARK: Keyboard

- (BOOL)canBecomeFirstResponder {
return YES;
}

- (BOOL)becomeFirstResponderWithString:(String)p_existing {
keyboard_text = p_existing;
return [self becomeFirstResponder];
}

- (BOOL)resignFirstResponder {
keyboard_text = String();
return [super resignFirstResponder];
}

- (void)deleteBackward {
if (keyboard_text.length()) {
keyboard_text.erase(keyboard_text.length() - 1, 1);
}
OSIPhone::get_singleton()->key(KEY_BACKSPACE, true);
}

- (BOOL)hasText {
return keyboard_text.length() > 0;
}

- (void)insertText:(NSString *)p_text {
String character;
character.parse_utf8([p_text UTF8String]);
keyboard_text = keyboard_text + character;
OSIPhone::get_singleton()->key(character[0] == 10 ? KEY_ENTER : character[0], true);
}

// MARK: Touches

- (void)initTouches {
Expand Down
37 changes: 37 additions & 0 deletions platform/iphone/keyboard_input_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*************************************************************************/
/* keyboard_input_view.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/

#import <UIKit/UIKit.h>

@interface GodotKeyboardInputView : UITextView

- (BOOL)becomeFirstResponderWithString:(NSString *)existingString;

@end
111 changes: 111 additions & 0 deletions platform/iphone/keyboard_input_view.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*************************************************************************/
/* keyboard_input_view.mm */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/

#import "keyboard_input_view.h"

#include "core/os/keyboard.h"
#include "os_iphone.h"

@interface GodotKeyboardInputView () <UITextViewDelegate>

@end

@implementation GodotKeyboardInputView

- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];

if (self) {
[self godot_commonInit];
}

return self;
}

- (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer {
self = [super initWithFrame:frame textContainer:textContainer];

if (self) {
[self godot_commonInit];
}

return self;
}

- (void)godot_commonInit {
self.hidden = YES;
self.delegate = self;
}

- (void)dealloc {
self.delegate = nil;
}

// MARK: Keyboard

- (BOOL)canBecomeFirstResponder {
return YES;
}

- (BOOL)becomeFirstResponderWithString:(NSString *)existingString {
self.text = existingString;
return [self becomeFirstResponder];
}

- (BOOL)resignFirstResponder {
self.text = nil;
return [super resignFirstResponder];
}

// MARK: Delegate

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if (textView != self) {
return NO;
}

if (text.length == 0) {
for (int i = 0; i < range.length; i++) {
OSIPhone::get_singleton()->key(KEY_BACKSPACE, true);
}
} else {
String characters;
characters.parse_utf8([text UTF8String]);

for (int i = 0; i < characters.size(); i++) {
int character = characters[i];
OSIPhone::get_singleton()->key(character == 10 ? KEY_ENTER : character, true);
}
}

return YES;
}

@end
6 changes: 4 additions & 2 deletions platform/iphone/os_iphone.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#import "app_delegate.h"
#import "device_metrics.h"
#import "godot_view.h"
#import "keyboard_input_view.h"
#import "native_video_view.h"
#import "view_controller.h"

Expand Down Expand Up @@ -453,11 +454,12 @@ void register_dynamic_symbol(char *name, void *address) {
};

void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
[AppDelegate.viewController.godotView becomeFirstResponderWithString:p_existing_text];
NSString *existingString = [[NSString alloc] initWithUTF8String:p_existing_text.utf8().get_data()];
[AppDelegate.viewController.keyboardView becomeFirstResponderWithString:existingString];
};

void OSIPhone::hide_virtual_keyboard() {
[AppDelegate.viewController.godotView resignFirstResponder];
[AppDelegate.viewController.keyboardView resignFirstResponder];
}

void OSIPhone::set_virtual_keyboard_height(int p_height) {
Expand Down
2 changes: 2 additions & 0 deletions platform/iphone/view_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@

@class GodotView;
@class GodotNativeVideoView;
@class GodotKeyboardInputView;

@interface ViewController : UIViewController <GKGameCenterControllerDelegate>

@property(nonatomic, readonly, strong) GodotView *godotView;
@property(nonatomic, readonly, strong) GodotNativeVideoView *videoView;
@property(nonatomic, readonly, strong) GodotKeyboardInputView *keyboardView;

// MARK: Native Video Player

Expand Down
9 changes: 8 additions & 1 deletion platform/iphone/view_controller.mm
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
#include "core/project_settings.h"
#import "godot_view.h"
#import "godot_view_renderer.h"
#import "keyboard_input_view.h"
#import "native_video_view.h"
#include "os_iphone.h"

@interface ViewController ()

@property(strong, nonatomic) GodotViewRenderer *renderer;
@property(strong, nonatomic) GodotNativeVideoView *videoView;
@property(strong, nonatomic) GodotKeyboardInputView *keyboardView;

@end

Expand Down Expand Up @@ -101,6 +103,10 @@ - (void)viewDidLoad {
}

- (void)observeKeyboard {
printf("******** setting up keyboard input view\n");
self.keyboardView = [GodotKeyboardInputView new];
[self.view addSubview:self.keyboardView];

printf("******** adding observer for keyboard show/hide\n");
[[NSNotificationCenter defaultCenter]
addObserver:self
Expand All @@ -118,7 +124,8 @@ - (void)dealloc {
[self.videoView stopVideo];
self.videoView = nil;

self.videoView = nil;
self.keyboardView = nil;

self.renderer = nil;

[[NSNotificationCenter defaultCenter] removeObserver:self];
Expand Down

0 comments on commit 74d5be7

Please sign in to comment.