Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] Implement raw mouse input support and captured mouse mode. #92276

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
touch_velocity_track.erase(st->get_index());
}

if (emulate_mouse_from_touch) {
if (emulate_mouse_from_touch && get_mouse_mode() != MouseMode::MOUSE_MODE_CAPTURED) {
bool translate = false;
if (st->is_pressed()) {
if (mouse_from_touch_index == -1) {
Expand Down Expand Up @@ -684,7 +684,7 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
sd->set_velocity(track.velocity);
sd->set_screen_velocity(track.screen_velocity);

if (emulate_mouse_from_touch && sd->get_index() == mouse_from_touch_index) {
if (emulate_mouse_from_touch && sd->get_index() == mouse_from_touch_index && get_mouse_mode() != MouseMode::MOUSE_MODE_CAPTURED) {
Ref<InputEventMouseMotion> motion_event;
motion_event.instantiate();

Expand Down
5 changes: 4 additions & 1 deletion misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
</array>
$additional_plist_content
$plist_launch_screen_name
<key>CADisableMinimumFrameDurationOnPhone</key><true/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
$ui_indirect_events
</dict>
</plist>
7 changes: 7 additions & 0 deletions platform/ios/display_server_ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class DisplayServerIOS : public DisplayServer {

int virtual_keyboard_height = 0;

MouseMode mouse_mode = MOUSE_MODE_VISIBLE;

void perform_event(const Ref<InputEvent> &p_event);

DisplayServerIOS(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, Error &r_error);
Expand Down Expand Up @@ -222,6 +224,11 @@ class DisplayServerIOS : public DisplayServer {
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) override;
virtual void virtual_keyboard_hide() override;

virtual void mouse_set_mode(MouseMode p_mode) override;
virtual MouseMode mouse_get_mode() const override;

virtual BitField<MouseButtonMask> mouse_get_button_state() const override;

void virtual_keyboard_set_height(int height);
virtual int virtual_keyboard_get_height() const override;

Expand Down
24 changes: 24 additions & 0 deletions platform/ios/display_server_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,30 @@ _FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text,
return virtual_keyboard_height;
}

void DisplayServerIOS::mouse_set_mode(DisplayServer::MouseMode p_mode) {
if (mouse_mode == p_mode) {
return;
}
ERR_FAIL_COND_MSG(p_mode == DisplayServer::MouseMode::MOUSE_MODE_HIDDEN || p_mode == DisplayServer::MouseMode::MOUSE_MODE_CONFINED || p_mode == DisplayServer::MouseMode::MOUSE_MODE_CONFINED_HIDDEN, "Confined and hidden mouse modes not supported.");

mouse_mode = p_mode;
if (@available(iOS 14, *)) {
[AppDelegate.viewController setNeedsUpdateOfPrefersPointerLocked];
}
}

DisplayServer::MouseMode DisplayServerIOS::mouse_get_mode() const {
return mouse_mode;
}

BitField<MouseButtonMask> DisplayServerIOS::mouse_get_button_state() const {
if (@available(iOS 14, *)) {
return [AppDelegate.viewController mouseGetButtonState];
} else {
return 0;
}
}

void DisplayServerIOS::clipboard_set(const String &p_text) {
[UIPasteboard generalPasteboard].string = [NSString stringWithUTF8String:p_text.utf8()];
}
Expand Down
3 changes: 3 additions & 0 deletions platform/ios/doc_classes/EditorExportPlatformIOS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
<member name="application/signature" type="String" setter="" getter="">
A four-character creator code that is specific to the bundle. Optional.
</member>
<member name="application/supports_indirect_input" type="bool" setter="" getter="">
If [code]true[/code], raw mouse/touchpad input is always used. Otherwise, it's only used in captured mode.
</member>
<member name="application/targeted_device_family" type="int" setter="" getter="">
Supported device family.
</member>
Expand Down
4 changes: 4 additions & 0 deletions platform/ios/export/export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)

r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/export_project_only"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/delete_old_export_files_unconditionally"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/supports_indirect_input"), true));

Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
Expand Down Expand Up @@ -747,6 +748,9 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
}
strnew += "\t</array>\n";
} else if (lines[i].contains("$ui_indirect_events")) {
bool ind = p_preset->get("application/supports_indirect_input");
strnew += lines[i].replace("$ui_indirect_events", ind ? "<true/>" : "<false/>") + "\n";
} else {
strnew += lines[i] + "\n";
}
Expand Down
15 changes: 15 additions & 0 deletions platform/ios/godot_view.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@

#import "godot_view.h"

#import "app_delegate.h"
#import "display_layer.h"
#import "display_server_ios.h"
#import "godot_view_renderer.h"
#import "view_controller.h"

#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
Expand Down Expand Up @@ -355,6 +357,9 @@ - (void)clearTouches {

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.type != UITouchTypeDirect && touch.type != UITouchTypePencil && AppDelegate.viewController.hasMouse) {
continue;
}
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self];
Expand All @@ -364,6 +369,9 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.type != UITouchTypeDirect && touch.type != UITouchTypePencil && AppDelegate.viewController.hasMouse) {
continue;
}
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
CGPoint touchPoint = [touch locationInView:self];
Expand All @@ -376,6 +384,10 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.type != UITouchTypeDirect && touch.type != UITouchTypePencil && AppDelegate.viewController.hasMouse) {
[self removeTouch:touch];
continue;
}
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
[self removeTouch:touch];
Expand All @@ -386,6 +398,9 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.type != UITouchTypeDirect && touch.type != UITouchTypePencil && AppDelegate.viewController.hasMouse) {
continue;
}
int tid = [self getTouchIDForTouch:touch];
ERR_FAIL_COND(tid == -1);
DisplayServerIOS::get_singleton()->touches_canceled(tid);
Expand Down
5 changes: 5 additions & 0 deletions platform/ios/view_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#import <UIKit/UIKit.h>

#include "core/input/input.h"

@class GodotView;
@class GodotNativeVideoView;
@class GodotKeyboardInputView;
Expand All @@ -38,5 +40,8 @@

@property(nonatomic, readonly, strong) GodotView *godotView;
@property(nonatomic, readonly, strong) GodotKeyboardInputView *keyboardView;
@property(nonatomic) bool hasMouse;

- (BitField<MouseButtonMask>)mouseGetButtonState;

@end
Loading
Loading