summaryrefslogtreecommitdiff
path: root/platform/ios
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios')
-rw-r--r--platform/ios/SCsub2
-rw-r--r--platform/ios/detect.py12
-rw-r--r--platform/ios/display_layer.h3
-rw-r--r--platform/ios/display_layer.mm29
-rw-r--r--platform/ios/display_server_ios.h10
-rw-r--r--platform/ios/display_server_ios.mm98
-rw-r--r--platform/ios/export/export_plugin.cpp7
-rw-r--r--platform/ios/godot_view.h5
-rw-r--r--platform/ios/godot_view.mm98
-rw-r--r--platform/ios/godot_view_gesture_recognizer.mm186
-rw-r--r--platform/ios/joypad_ios.mm19
-rw-r--r--platform/ios/key_mapping_ios.h (renamed from platform/ios/godot_view_gesture_recognizer.h)24
-rw-r--r--platform/ios/key_mapping_ios.mm186
-rw-r--r--platform/ios/keyboard_input_view.mm18
-rw-r--r--platform/ios/view_controller.mm59
15 files changed, 414 insertions, 342 deletions
diff --git a/platform/ios/SCsub b/platform/ios/SCsub
index bf12ab6dd7..18ba6617af 100644
--- a/platform/ios/SCsub
+++ b/platform/ios/SCsub
@@ -17,9 +17,9 @@ ios_lib = [
"display_layer.mm",
"godot_app_delegate.m",
"godot_view_renderer.mm",
- "godot_view_gesture_recognizer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
+ "key_mapping_ios.mm",
]
env_ios = env.Clone()
diff --git a/platform/ios/detect.py b/platform/ios/detect.py
index 38e62134b5..71612cf1fa 100644
--- a/platform/ios/detect.py
+++ b/platform/ios/detect.py
@@ -99,8 +99,8 @@ def configure(env: "Environment"):
if env["ios_simulator"]:
detect_darwin_sdk_path("iossimulator", env)
- env.Append(ASFLAGS=["-mios-simulator-version-min=13.0"])
- env.Append(CCFLAGS=["-mios-simulator-version-min=13.0"])
+ env.Append(ASFLAGS=["-mios-simulator-version-min=11.0"])
+ env.Append(CCFLAGS=["-mios-simulator-version-min=11.0"])
env.extra_suffix = ".simulator" + env.extra_suffix
else:
detect_darwin_sdk_path("ios", env)
@@ -153,3 +153,11 @@ def configure(env: "Environment"):
if env["vulkan"]:
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+
+ if env["opengl3"]:
+ env.Append(CPPDEFINES=["GLES3_ENABLED"])
+ env.Prepend(
+ CPPPATH=[
+ "$IOS_SDK_PATH/System/Library/Frameworks/OpenGLES.framework/Headers",
+ ]
+ )
diff --git a/platform/ios/display_layer.h b/platform/ios/display_layer.h
index 10f42264df..e719a42cd9 100644
--- a/platform/ios/display_layer.h
+++ b/platform/ios/display_layer.h
@@ -33,7 +33,8 @@
@protocol DisplayLayer <NSObject>
-- (void)renderDisplayLayer;
+- (void)startRenderDisplayLayer;
+- (void)stopRenderDisplayLayer;
- (void)initializeDisplayLayer;
- (void)layoutDisplayLayer;
diff --git a/platform/ios/display_layer.mm b/platform/ios/display_layer.mm
index 24614fea56..3129ebb276 100644
--- a/platform/ios/display_layer.mm
+++ b/platform/ios/display_layer.mm
@@ -60,7 +60,10 @@
- (void)layoutDisplayLayer {
}
-- (void)renderDisplayLayer {
+- (void)startRenderDisplayLayer {
+}
+
+- (void)stopRenderDisplayLayer {
}
@end
@@ -76,8 +79,6 @@
}
- (void)initializeDisplayLayer {
- // Get our backing layer
-
// Configure it so that it is opaque, does not retain the contents of the backbuffer when displayed, and uses RGBA8888 color.
self.opaque = YES;
self.drawableProperties = [NSDictionary
@@ -87,8 +88,6 @@
kEAGLDrawablePropertyColorFormat,
nil];
- // FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
-
// Create GL ES 3 context
if (GLOBAL_GET("rendering/renderer/rendering_method") == "gl_compatibility") {
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
@@ -115,8 +114,22 @@
[self createFramebuffer];
}
-- (void)renderDisplayLayer {
+- (void)startRenderDisplayLayer {
[EAGLContext setCurrentContext:context];
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
+}
+
+- (void)stopRenderDisplayLayer {
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
+ [context presentRenderbuffer:GL_RENDERBUFFER_OES];
+
+#ifdef DEBUG_ENABLED
+ GLenum err = glGetError();
+ if (err) {
+ NSLog(@"DrawView: %x error", err);
+ }
+#endif
}
- (void)dealloc {
@@ -154,11 +167,15 @@
return NO;
}
+ GLES3::TextureStorage::system_fbo = viewFramebuffer;
+
return YES;
}
// Clean up any buffers we have allocated.
- (void)destroyFramebuffer {
+ GLES3::TextureStorage::system_fbo = 0;
+
glDeleteFramebuffersOES(1, &viewFramebuffer);
viewFramebuffer = 0;
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h
index dd1157f668..6eaa7c8edc 100644
--- a/platform/ios/display_server_ios.h
+++ b/platform/ios/display_server_ios.h
@@ -47,6 +47,10 @@
#endif
#endif
+#if defined(GLES3_ENABLED)
+#include "drivers/gles3/rasterizer_gles3.h"
+#endif // GLES3_ENABLED
+
#import <Foundation/Foundation.h>
#import <QuartzCore/CAMetalLayer.h>
@@ -109,11 +113,12 @@ public:
void touch_press(int p_idx, int p_x, int p_y, bool p_pressed, bool p_double_click);
void touch_drag(int p_idx, int p_prev_x, int p_prev_y, int p_x, int p_y, float p_pressure, Vector2 p_tilt);
- void touches_cancelled(int p_idx);
+ void touches_canceled(int p_idx);
// MARK: Keyboard
- void key(Key p_key, char32_t p_char, bool p_pressed);
+ void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed);
+ bool is_keyboard_active() const;
// MARK: Motion
@@ -216,6 +221,7 @@ public:
virtual bool screen_is_kept_on() const override;
void resize_window(CGSize size);
+ virtual void swap_buffers() override {}
};
#endif // DISPLAY_SERVER_IOS_H
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index bea88a7f9b..469bc9be17 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -36,6 +36,7 @@
#import "device_metrics.h"
#import "godot_view.h"
#include "ios.h"
+#import "key_mapping_ios.h"
#import "keyboard_input_view.h"
#include "os_ios.h"
#include "tts_ios.h"
@@ -50,52 +51,14 @@ DisplayServerIOS *DisplayServerIOS::get_singleton() {
}
DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
+ KeyMappingIOS::initialize();
+
rendering_driver = p_rendering_driver;
// Init TTS
tts = [[TTS_IOS alloc] init];
-#if defined(GLES3_ENABLED)
- // FIXME: Add support for both OpenGL and Vulkan when OpenGL is implemented
- // again,
- // Note that we should be checking "opengl3" as the driver, might never enable this seeing OpenGL is deprecated on iOS
- // We are hardcoding the rendering_driver to "vulkan" down below
-
- if (rendering_driver == "opengl3") {
- bool gl_initialization_error = false;
-
- // FIXME: Add Vulkan support via MoltenVK. Add fallback code back?
-
- if (RasterizerGLES3::is_viable() == OK) {
- RasterizerGLES3::register_config();
- RasterizerGLES3::make_current();
- } else {
- gl_initialization_error = true;
- }
-
- if (gl_initialization_error) {
- OS::get_singleton()->alert("Your device does not support any of the supported OpenGL versions.", "Unable to initialize video driver");
- // return ERR_UNAVAILABLE;
- }
-
- // rendering_server = memnew(RenderingServerDefault);
- // // FIXME: Reimplement threaded rendering
- // if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
- // rendering_server = memnew(RenderingServerWrapMT(rendering_server,
- // false));
- // }
- // rendering_server->init();
- // rendering_server->cursor_set_visible(false, 0);
-
- // reset this to what it should be, it will have been set to 0 after
- // rendering_server->init() is called
- // RasterizerStorageGLES3system_fbo = gl_view_base_fb;
- }
-#endif
-
#if defined(VULKAN_ENABLED)
- rendering_driver = "vulkan";
-
context_vulkan = nullptr;
rendering_device_vulkan = nullptr;
@@ -110,13 +73,14 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"vulkan"];
if (!layer) {
- ERR_FAIL_MSG("Failed to create iOS rendering layer.");
+ ERR_FAIL_MSG("Failed to create iOS Vulkan rendering layer.");
}
Size2i size = Size2i(layer.bounds.size.width, layer.bounds.size.height) * screen_get_max_scale();
if (context_vulkan->window_create(MAIN_WINDOW_ID, p_vsync_mode, layer, size.width, size.height) != OK) {
memdelete(context_vulkan);
context_vulkan = nullptr;
+ r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Failed to create Vulkan window.");
}
@@ -127,6 +91,18 @@ DisplayServerIOS::DisplayServerIOS(const String &p_rendering_driver, WindowMode
}
#endif
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ CALayer *layer = [AppDelegate.viewController.godotView initializeRenderingForDriver:@"opengl3"];
+
+ if (!layer) {
+ ERR_FAIL_MSG("Failed to create iOS OpenGLES rendering layer.");
+ }
+
+ RasterizerGLES3::make_current();
+ }
+#endif
+
bool keep_screen_on = bool(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
screen_set_keep_on(keep_screen_on);
@@ -252,20 +228,35 @@ void DisplayServerIOS::perform_event(const Ref<InputEvent> &p_event) {
Input::get_singleton()->parse_input_event(p_event);
}
-void DisplayServerIOS::touches_cancelled(int p_idx) {
+void DisplayServerIOS::touches_canceled(int p_idx) {
touch_press(p_idx, -1, -1, false, false);
}
// MARK: Keyboard
-void DisplayServerIOS::key(Key p_key, char32_t p_char, bool p_pressed) {
+void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed) {
Ref<InputEventKey> ev;
ev.instantiate();
ev->set_echo(false);
ev->set_pressed(p_pressed);
- ev->set_keycode(p_key);
- ev->set_physical_keycode(p_key);
- ev->set_unicode(p_char);
+ ev->set_keycode(fix_keycode(p_char, p_key));
+ if (@available(iOS 13.4, *)) {
+ if (p_key != Key::SHIFT) {
+ ev->set_shift_pressed(p_modifier & UIKeyModifierShift);
+ }
+ if (p_key != Key::CTRL) {
+ ev->set_ctrl_pressed(p_modifier & UIKeyModifierControl);
+ }
+ if (p_key != Key::ALT) {
+ ev->set_alt_pressed(p_modifier & UIKeyModifierAlternate);
+ }
+ if (p_key != Key::META) {
+ ev->set_meta_pressed(p_modifier & UIKeyModifierCommand);
+ }
+ }
+ ev->set_key_label(p_unshifted);
+ ev->set_physical_keycode(p_physical);
+ ev->set_unicode(fix_unicode(p_char));
perform_event(ev);
}
@@ -643,6 +634,10 @@ void DisplayServerIOS::virtual_keyboard_show(const String &p_existing_text, cons
cursorEnd:_convert_utf32_offset_to_utf16(p_existing_text, p_cursor_end)];
}
+bool DisplayServerIOS::is_keyboard_active() const {
+ return [AppDelegate.viewController.keyboardView isFirstResponder];
+}
+
void DisplayServerIOS::virtual_keyboard_hide() {
[AppDelegate.viewController.keyboardView resignFirstResponder];
}
@@ -689,15 +684,18 @@ void DisplayServerIOS::resize_window(CGSize viewSize) {
void DisplayServerIOS::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
- context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ if (context_vulkan) {
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ }
#endif
}
DisplayServer::VSyncMode DisplayServerIOS::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
#if defined(VULKAN_ENABLED)
- return context_vulkan->get_vsync_mode(p_window);
-#else
- return DisplayServer::VSYNC_ENABLED;
+ if (context_vulkan) {
+ return context_vulkan->get_vsync_mode(p_window);
+ }
#endif
+ return DisplayServer::VSYNC_ENABLED;
}
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index ccd3480d11..c6f7ec09b1 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -43,6 +43,7 @@
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
// Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
r_features->push_back("etc2");
+ r_features->push_back("astc");
Vector<String> architectures = _get_preset_architectures(p_preset);
for (int i = 0; i < architectures.size(); ++i) {
@@ -1572,7 +1573,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
int ret = unzGoToFirstFile(src_pkg_zip);
Vector<uint8_t> project_file_data;
while (ret == UNZ_OK) {
-#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED)
bool is_execute = false;
#endif
@@ -1605,7 +1606,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
continue; //ignore!
}
found_library = true;
-#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED)
is_execute = true;
#endif
file = file.replace(library_to_use, binary_name + ".xcframework");
@@ -1648,7 +1649,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
f->store_buffer(data.ptr(), data.size());
}
-#if defined(MACOS_ENABLED) || defined(X11_ENABLED)
+#if defined(MACOS_ENABLED) || defined(LINUXBSD_ENABLED)
if (is_execute) {
// we need execute rights on this file
chmod(file.utf8().get_data(), 0755);
diff --git a/platform/ios/godot_view.h b/platform/ios/godot_view.h
index 077584baa6..b00ca37ebe 100644
--- a/platform/ios/godot_view.h
+++ b/platform/ios/godot_view.h
@@ -59,9 +59,4 @@ class String;
- (void)stopRendering;
- (void)startRendering;
-- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
-
@end
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 1c8c578bd2..fafec79bf6 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -35,7 +35,6 @@
#include "core/string/ustring.h"
#import "display_layer.h"
#include "display_server_ios.h"
-#import "godot_view_gesture_recognizer.h"
#import "godot_view_renderer.h"
#import <CoreMotion/CoreMotion.h>
@@ -60,8 +59,6 @@ static const float earth_gravity = 9.80665;
@property(strong, nonatomic) CMMotionManager *motionManager;
-@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer;
-
@end
@implementation GodotView
@@ -74,16 +71,20 @@ static const float earth_gravity = 9.80665;
CALayer<DisplayLayer> *layer;
if ([driverName isEqualToString:@"vulkan"]) {
+#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
+ if (@available(iOS 13, *)) {
+ layer = [GodotMetalLayer layer];
+ } else {
+ return nil;
+ }
+#else
layer = [GodotMetalLayer layer];
+#endif
} else if ([driverName isEqualToString:@"opengl3"]) {
if (@available(iOS 13, *)) {
NSLog(@"OpenGL ES is deprecated on iOS 13");
}
-#if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR
- return nil;
-#else
layer = [GodotOpenGLLayer layer];
-#endif
} else {
return nil;
}
@@ -144,10 +145,6 @@ static const float earth_gravity = 9.80665;
[self.animationTimer invalidate];
self.animationTimer = nil;
}
-
- if (self.delayGestureRecognizer) {
- self.delayGestureRecognizer = nil;
- }
}
- (void)godot_commonInit {
@@ -167,11 +164,6 @@ static const float earth_gravity = 9.80665;
self.motionManager = nil;
}
}
-
- // Initialize delay gesture recognizer
- GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init];
- self.delayGestureRecognizer = gestureRecognizer;
- [self addGestureRecognizer:self.delayGestureRecognizer];
}
- (void)stopRendering {
@@ -238,7 +230,7 @@ static const float earth_gravity = 9.80665;
[self.displayLink setPaused:NO];
}
- [self.renderingLayer renderDisplayLayer];
+ [self.renderingLayer startRenderDisplayLayer];
if (!self.renderer) {
return;
@@ -258,6 +250,8 @@ static const float earth_gravity = 9.80665;
[self handleMotion];
[self.renderer renderOnView:self];
+
+ [self.renderingLayer stopRenderDisplayLayer];
}
- (BOOL)canRender {
@@ -341,58 +335,42 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touchesSet containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
- }
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
}
}
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- CGPoint prev_point = [touch previousLocationInView:self];
- CGFloat alt = [touch altitudeAngle];
- CGVector azim = [touch azimuthUnitVectorInView:self];
- DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
- }
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ CGPoint prev_point = [touch previousLocationInView:self];
+ CGFloat alt = [touch altitudeAngle];
+ CGVector azim = [touch azimuthUnitVectorInView:self];
+ DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
}
}
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- [self removeTouch:touch];
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
- }
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ [self removeTouch:touch];
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
}
}
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- DisplayServerIOS::get_singleton()->touches_cancelled(tid);
- }
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ DisplayServerIOS::get_singleton()->touches_canceled(tid);
}
[self clearTouches];
}
diff --git a/platform/ios/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm
deleted file mode 100644
index 9b71228864..0000000000
--- a/platform/ios/godot_view_gesture_recognizer.mm
+++ /dev/null
@@ -1,186 +0,0 @@
-/**************************************************************************/
-/* godot_view_gesture_recognizer.mm */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "godot_view_gesture_recognizer.h"
-
-#import "godot_view.h"
-
-#include "core/config/project_settings.h"
-
-// Minimum distance for touches to move to fire
-// a delay timer before scheduled time.
-// Should be the low enough to not cause issues with dragging
-// but big enough to allow click to work.
-const CGFloat kGLGestureMovementDistance = 0.5;
-
-@interface GodotViewGestureRecognizer ()
-
-@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval;
-
-@end
-
-@interface GodotViewGestureRecognizer ()
-
-// Timer used to delay begin touch message.
-// Should work as simple emulation of UIDelayedAction
-@property(strong, nonatomic) NSTimer *delayTimer;
-
-// Delayed touch parameters
-@property(strong, nonatomic) NSSet *delayedTouches;
-@property(strong, nonatomic) UIEvent *delayedEvent;
-
-@end
-
-@implementation GodotViewGestureRecognizer
-
-- (GodotView *)godotView {
- return (GodotView *)self.view;
-}
-
-- (instancetype)init {
- self = [super init];
-
- self.cancelsTouchesInView = YES;
- self.delaysTouchesBegan = YES;
- self.delaysTouchesEnded = YES;
- self.requiresExclusiveTouchType = NO;
-
- self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay");
-
- return self;
-}
-
-- (void)dealloc {
- if (self.delayTimer) {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
- }
-
- if (self.delayedTouches) {
- self.delayedTouches = nil;
- }
-
- if (self.delayedEvent) {
- self.delayedEvent = nil;
- }
-}
-
-- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- self.delayedTouches = touches;
- self.delayedEvent = event;
-
- self.delayTimer = [NSTimer
- scheduledTimerWithTimeInterval:self.delayTimeInterval
- target:self
- selector:@selector(fireDelayedTouches:)
- userInfo:nil
- repeats:NO];
-}
-
-- (void)fireDelayedTouches:(id)timer {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
-
- if (self.delayedTouches) {
- [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent];
- }
-
- self.delayedTouches = nil;
- self.delayedEvent = nil;
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan];
- [self delayTouches:cleared andEvent:event];
-
- [super touchesBegan:touches withEvent:event];
-}
-
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved];
-
- if (self.delayTimer) {
- // We should check if movement was significant enough to fire an event
- // for dragging to work correctly.
- for (UITouch *touch in cleared) {
- CGPoint from = [touch locationInView:self.godotView];
- CGPoint to = [touch previousLocationInView:self.godotView];
- CGFloat xDistance = from.x - to.x;
- CGFloat yDistance = from.y - to.y;
-
- CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance);
-
- // Early exit, since one of touches has moved enough to fire a drag event.
- if (distance > kGLGestureMovementDistance) {
- [self.delayTimer fire];
- [self.godotView godotTouchesMoved:cleared withEvent:event];
- return;
- }
- }
-
- return;
- }
-
- [self.godotView godotTouchesMoved:cleared withEvent:event];
-
- [super touchesMoved:touches withEvent:event];
-}
-
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded];
- [self.godotView godotTouchesEnded:cleared withEvent:event];
-
- [super touchesEnded:touches withEvent:event];
-}
-
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
- [self.godotView godotTouchesCancelled:touches withEvent:event];
-
- [super touchesCancelled:touches withEvent:event];
-}
-
-- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave {
- NSMutableSet *cleared = [touches mutableCopy];
-
- for (UITouch *touch in touches) {
- if (touch.view != self.view || touch.phase != phaseToSave) {
- [cleared removeObject:touch];
- }
- }
-
- return cleared;
-}
-
-@end
diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm
index 057f439b81..9194b09ef6 100644
--- a/platform/ios/joypad_ios.mm
+++ b/platform/ios/joypad_ios.mm
@@ -305,6 +305,25 @@ void JoypadIOS::start_processing() {
float value = gamepad.rightTrigger.value;
Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value);
}
+
+ if (@available(iOS 13, *)) {
+ // iOS uses 'buttonOptions' and 'buttonMenu' names for BACK and START joy buttons.
+ if (element == gamepad.buttonOptions) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::BACK,
+ gamepad.buttonOptions.isPressed);
+ } else if (element == gamepad.buttonMenu) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::START,
+ gamepad.buttonMenu.isPressed);
+ }
+ }
+
+ if (@available(iOS 14, *)) {
+ // iOS uses 'buttonHome' for the GUIDE joy button.
+ if (element == gamepad.buttonHome) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::GUIDE,
+ gamepad.buttonHome.isPressed);
+ }
+ }
};
} else if (controller.microGamepad != nil) {
// micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad
diff --git a/platform/ios/godot_view_gesture_recognizer.h b/platform/ios/key_mapping_ios.h
index 57bfc75568..6cc61175bb 100644
--- a/platform/ios/godot_view_gesture_recognizer.h
+++ b/platform/ios/key_mapping_ios.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* godot_view_gesture_recognizer.h */
+/* key_mapping_ios.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,19 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-// GLViewGestureRecognizer allows iOS gestures to work correctly by
-// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer.
-// It catches all gestures incoming to UIView and delays them for 150ms
-// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer)
-// If touch cancellation or end message is fired it fires delayed
-// begin touch immediately as well as last touch signal
+#ifndef KEY_MAPPING_IOS_H
+#define KEY_MAPPING_IOS_H
-#import <UIKit/UIKit.h>
+#include "core/os/keyboard.h"
-@interface GodotViewGestureRecognizer : UIGestureRecognizer
+#import <UIKit/UIKit.h>
-@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval;
+class KeyMappingIOS {
+ KeyMappingIOS() {}
-- (instancetype)init;
+public:
+ static void initialize();
+ static Key remap_key(CFIndex p_keycode);
+};
-@end
+#endif // KEY_MAPPING_IOS_H
diff --git a/platform/ios/key_mapping_ios.mm b/platform/ios/key_mapping_ios.mm
new file mode 100644
index 0000000000..c378186778
--- /dev/null
+++ b/platform/ios/key_mapping_ios.mm
@@ -0,0 +1,186 @@
+/**************************************************************************/
+/* key_mapping_ios.mm */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/**************************************************************************/
+
+#include "key_mapping_ios.h"
+
+#include "core/templates/hash_map.h"
+
+struct HashMapHasherKeys {
+ static _FORCE_INLINE_ uint32_t hash(const Key p_key) { return hash_fmix32(static_cast<uint32_t>(p_key)); }
+ static _FORCE_INLINE_ uint32_t hash(const CFIndex p_key) { return hash_fmix32(p_key); }
+};
+
+HashMap<CFIndex, Key, HashMapHasherKeys> keyusage_map;
+
+void KeyMappingIOS::initialize() {
+ if (@available(iOS 13.4, *)) {
+ keyusage_map[UIKeyboardHIDUsageKeyboardA] = Key::A;
+ keyusage_map[UIKeyboardHIDUsageKeyboardB] = Key::B;
+ keyusage_map[UIKeyboardHIDUsageKeyboardC] = Key::C;
+ keyusage_map[UIKeyboardHIDUsageKeyboardD] = Key::D;
+ keyusage_map[UIKeyboardHIDUsageKeyboardE] = Key::E;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF] = Key::F;
+ keyusage_map[UIKeyboardHIDUsageKeyboardG] = Key::G;
+ keyusage_map[UIKeyboardHIDUsageKeyboardH] = Key::H;
+ keyusage_map[UIKeyboardHIDUsageKeyboardI] = Key::I;
+ keyusage_map[UIKeyboardHIDUsageKeyboardJ] = Key::J;
+ keyusage_map[UIKeyboardHIDUsageKeyboardK] = Key::K;
+ keyusage_map[UIKeyboardHIDUsageKeyboardL] = Key::L;
+ keyusage_map[UIKeyboardHIDUsageKeyboardM] = Key::M;
+ keyusage_map[UIKeyboardHIDUsageKeyboardN] = Key::N;
+ keyusage_map[UIKeyboardHIDUsageKeyboardO] = Key::O;
+ keyusage_map[UIKeyboardHIDUsageKeyboardP] = Key::P;
+ keyusage_map[UIKeyboardHIDUsageKeyboardQ] = Key::Q;
+ keyusage_map[UIKeyboardHIDUsageKeyboardR] = Key::R;
+ keyusage_map[UIKeyboardHIDUsageKeyboardS] = Key::S;
+ keyusage_map[UIKeyboardHIDUsageKeyboardT] = Key::T;
+ keyusage_map[UIKeyboardHIDUsageKeyboardU] = Key::U;
+ keyusage_map[UIKeyboardHIDUsageKeyboardV] = Key::V;
+ keyusage_map[UIKeyboardHIDUsageKeyboardW] = Key::W;
+ keyusage_map[UIKeyboardHIDUsageKeyboardX] = Key::X;
+ keyusage_map[UIKeyboardHIDUsageKeyboardY] = Key::Y;
+ keyusage_map[UIKeyboardHIDUsageKeyboardZ] = Key::Z;
+ keyusage_map[UIKeyboardHIDUsageKeyboard0] = Key::KEY_0;
+ keyusage_map[UIKeyboardHIDUsageKeyboard1] = Key::KEY_1;
+ keyusage_map[UIKeyboardHIDUsageKeyboard2] = Key::KEY_2;
+ keyusage_map[UIKeyboardHIDUsageKeyboard3] = Key::KEY_3;
+ keyusage_map[UIKeyboardHIDUsageKeyboard4] = Key::KEY_4;
+ keyusage_map[UIKeyboardHIDUsageKeyboard5] = Key::KEY_5;
+ keyusage_map[UIKeyboardHIDUsageKeyboard6] = Key::KEY_6;
+ keyusage_map[UIKeyboardHIDUsageKeyboard7] = Key::KEY_7;
+ keyusage_map[UIKeyboardHIDUsageKeyboard8] = Key::KEY_8;
+ keyusage_map[UIKeyboardHIDUsageKeyboard9] = Key::KEY_9;
+ keyusage_map[UIKeyboardHIDUsageKeyboardBackslash] = Key::BACKSLASH;
+ keyusage_map[UIKeyboardHIDUsageKeyboardCloseBracket] = Key::BRACKETRIGHT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardComma] = Key::COMMA;
+ keyusage_map[UIKeyboardHIDUsageKeyboardEqualSign] = Key::EQUAL;
+ keyusage_map[UIKeyboardHIDUsageKeyboardHyphen] = Key::MINUS;
+ keyusage_map[UIKeyboardHIDUsageKeyboardNonUSBackslash] = Key::SECTION;
+ keyusage_map[UIKeyboardHIDUsageKeyboardNonUSPound] = Key::ASCIITILDE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardOpenBracket] = Key::BRACKETLEFT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardPeriod] = Key::PERIOD;
+ keyusage_map[UIKeyboardHIDUsageKeyboardQuote] = Key::QUOTEDBL;
+ keyusage_map[UIKeyboardHIDUsageKeyboardSemicolon] = Key::SEMICOLON;
+ keyusage_map[UIKeyboardHIDUsageKeyboardSeparator] = Key::SECTION;
+ keyusage_map[UIKeyboardHIDUsageKeyboardSlash] = Key::SLASH;
+ keyusage_map[UIKeyboardHIDUsageKeyboardSpacebar] = Key::SPACE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardCapsLock] = Key::CAPSLOCK;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLeftAlt] = Key::ALT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLeftControl] = Key::CTRL;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLeftShift] = Key::SHIFT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardRightAlt] = Key::ALT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardRightControl] = Key::CTRL;
+ keyusage_map[UIKeyboardHIDUsageKeyboardRightShift] = Key::SHIFT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardScrollLock] = Key::SCROLLLOCK;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLeftArrow] = Key::LEFT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardRightArrow] = Key::RIGHT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardUpArrow] = Key::UP;
+ keyusage_map[UIKeyboardHIDUsageKeyboardDownArrow] = Key::DOWN;
+ keyusage_map[UIKeyboardHIDUsageKeyboardPageUp] = Key::PAGEUP;
+ keyusage_map[UIKeyboardHIDUsageKeyboardPageDown] = Key::PAGEDOWN;
+ keyusage_map[UIKeyboardHIDUsageKeyboardHome] = Key::HOME;
+ keyusage_map[UIKeyboardHIDUsageKeyboardEnd] = Key::END;
+ keyusage_map[UIKeyboardHIDUsageKeyboardDeleteForward] = Key::KEY_DELETE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardDeleteOrBackspace] = Key::BACKSPACE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardEscape] = Key::ESCAPE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardInsert] = Key::INSERT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardReturn] = Key::ENTER;
+ keyusage_map[UIKeyboardHIDUsageKeyboardTab] = Key::TAB;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF1] = Key::F1;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF2] = Key::F2;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF3] = Key::F3;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF4] = Key::F4;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF5] = Key::F5;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF6] = Key::F6;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF7] = Key::F7;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF8] = Key::F8;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF9] = Key::F9;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF10] = Key::F10;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF11] = Key::F11;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF12] = Key::F12;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF13] = Key::F13;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF14] = Key::F14;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF15] = Key::F15;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF16] = Key::F16;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF17] = Key::F17;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF18] = Key::F18;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF19] = Key::F19;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF20] = Key::F20;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF21] = Key::F21;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF22] = Key::F22;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF23] = Key::F23;
+ keyusage_map[UIKeyboardHIDUsageKeyboardF24] = Key::F24;
+ keyusage_map[UIKeyboardHIDUsageKeypad0] = Key::KP_0;
+ keyusage_map[UIKeyboardHIDUsageKeypad1] = Key::KP_1;
+ keyusage_map[UIKeyboardHIDUsageKeypad2] = Key::KP_2;
+ keyusage_map[UIKeyboardHIDUsageKeypad3] = Key::KP_3;
+ keyusage_map[UIKeyboardHIDUsageKeypad4] = Key::KP_4;
+ keyusage_map[UIKeyboardHIDUsageKeypad5] = Key::KP_5;
+ keyusage_map[UIKeyboardHIDUsageKeypad6] = Key::KP_6;
+ keyusage_map[UIKeyboardHIDUsageKeypad7] = Key::KP_7;
+ keyusage_map[UIKeyboardHIDUsageKeypad8] = Key::KP_8;
+ keyusage_map[UIKeyboardHIDUsageKeypad9] = Key::KP_9;
+ keyusage_map[UIKeyboardHIDUsageKeypadAsterisk] = Key::KP_MULTIPLY;
+ keyusage_map[UIKeyboardHIDUsageKeyboardGraveAccentAndTilde] = Key::BAR;
+ keyusage_map[UIKeyboardHIDUsageKeypadEnter] = Key::KP_ENTER;
+ keyusage_map[UIKeyboardHIDUsageKeypadHyphen] = Key::KP_SUBTRACT;
+ keyusage_map[UIKeyboardHIDUsageKeypadNumLock] = Key::NUMLOCK;
+ keyusage_map[UIKeyboardHIDUsageKeypadPeriod] = Key::KP_PERIOD;
+ keyusage_map[UIKeyboardHIDUsageKeypadPlus] = Key::KP_ADD;
+ keyusage_map[UIKeyboardHIDUsageKeypadSlash] = Key::KP_DIVIDE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardPause] = Key::PAUSE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardStop] = Key::STOP;
+ keyusage_map[UIKeyboardHIDUsageKeyboardMute] = Key::VOLUMEMUTE;
+ keyusage_map[UIKeyboardHIDUsageKeyboardVolumeUp] = Key::VOLUMEUP;
+ keyusage_map[UIKeyboardHIDUsageKeyboardVolumeDown] = Key::VOLUMEDOWN;
+ keyusage_map[UIKeyboardHIDUsageKeyboardFind] = Key::SEARCH;
+ keyusage_map[UIKeyboardHIDUsageKeyboardHelp] = Key::HELP;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLeftGUI] = Key::META;
+ keyusage_map[UIKeyboardHIDUsageKeyboardRightGUI] = Key::META;
+ keyusage_map[UIKeyboardHIDUsageKeyboardMenu] = Key::MENU;
+ keyusage_map[UIKeyboardHIDUsageKeyboardPrintScreen] = Key::PRINT;
+ keyusage_map[UIKeyboardHIDUsageKeyboardReturnOrEnter] = Key::ENTER;
+ keyusage_map[UIKeyboardHIDUsageKeyboardSysReqOrAttention] = Key::SYSREQ;
+ keyusage_map[0x01AE] = Key::KEYBOARD; // On-screen keyboard key on smart connector keyboard.
+ keyusage_map[0x029D] = Key::GLOBE; // "Globe" key on smart connector / Mac keyboard.
+ keyusage_map[UIKeyboardHIDUsageKeyboardLANG1] = Key::JIS_EISU;
+ keyusage_map[UIKeyboardHIDUsageKeyboardLANG2] = Key::JIS_KANA;
+ }
+}
+
+Key KeyMappingIOS::remap_key(CFIndex p_keycode) {
+ if (@available(iOS 13.4, *)) {
+ const Key *key = keyusage_map.getptr(p_keycode);
+ if (key) {
+ return *key;
+ }
+ }
+ return Key::NONE;
+}
diff --git a/platform/ios/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm
index f40db48ee3..2764403d68 100644
--- a/platform/ios/keyboard_input_view.mm
+++ b/platform/ios/keyboard_input_view.mm
@@ -115,8 +115,8 @@
- (void)deleteText:(NSInteger)charactersToDelete {
for (int i = 0; i < charactersToDelete; i++) {
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, true);
- DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, false);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true);
+ DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false);
}
}
@@ -134,20 +134,10 @@
key = Key::ENTER;
} else if (character == 0x2006) {
key = Key::SPACE;
- } else if (character == U'¥') {
- key = Key::YEN;
- } else if (character == U'§') {
- key = Key::SECTION;
- } else if (character >= 0x20 && character <= 0x7E) { // ASCII.
- if (character > 0x60 && character < 0x7B) { // Lowercase ASCII.
- key = (Key)(character - 32);
- } else {
- key = (Key)character;
- }
}
- DisplayServerIOS::get_singleton()->key(key, character, true);
- DisplayServerIOS::get_singleton()->key(key, character, false);
+ DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, true);
+ DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, false);
}
}
diff --git a/platform/ios/view_controller.mm b/platform/ios/view_controller.mm
index b787ed6709..a5aba201d7 100644
--- a/platform/ios/view_controller.mm
+++ b/platform/ios/view_controller.mm
@@ -33,6 +33,7 @@
#include "display_server_ios.h"
#import "godot_view.h"
#import "godot_view_renderer.h"
+#import "key_mapping_ios.h"
#import "keyboard_input_view.h"
#include "os_ios.h"
@@ -54,6 +55,64 @@
return (GodotView *)self.view;
}
+- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+ [super pressesBegan:presses withEvent:event];
+
+ if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) {
+ return;
+ }
+ if (@available(iOS 13.4, *)) {
+ for (UIPress *press in presses) {
+ String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]);
+ String u32text = String::utf8([press.key.characters UTF8String]);
+ Key key = KeyMappingIOS::remap_key(press.key.keyCode);
+
+ if (press.key.keyCode == 0 && u32text.is_empty() && u32lbl.is_empty()) {
+ continue;
+ }
+
+ char32_t us = 0;
+ if (!u32lbl.is_empty() && !u32lbl.begins_with("UIKey")) {
+ us = u32lbl[0];
+ }
+
+ if (!u32text.is_empty() && !u32text.begins_with("UIKey")) {
+ for (int i = 0; i < u32text.length(); i++) {
+ const char32_t c = u32text[i];
+ DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true);
+ }
+ } else {
+ DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true);
+ }
+ }
+ }
+}
+
+- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
+ [super pressesEnded:presses withEvent:event];
+
+ if (!DisplayServerIOS::get_singleton() || DisplayServerIOS::get_singleton()->is_keyboard_active()) {
+ return;
+ }
+ if (@available(iOS 13.4, *)) {
+ for (UIPress *press in presses) {
+ String u32lbl = String::utf8([press.key.charactersIgnoringModifiers UTF8String]);
+ Key key = KeyMappingIOS::remap_key(press.key.keyCode);
+
+ if (press.key.keyCode == 0 && u32lbl.is_empty()) {
+ continue;
+ }
+
+ char32_t us = 0;
+ if (!u32lbl.is_empty() && !u32lbl.begins_with("UIKey")) {
+ us = u32lbl[0];
+ }
+
+ DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false);
+ }
+ }
+}
+
- (void)loadView {
GodotView *view = [[GodotView alloc] init];
GodotViewRenderer *renderer = [[GodotViewRenderer alloc] init];