Godot: bbcode in richtextlabel can not go to url on iOS

Created on 13 Jun 2020  路  11Comments  路  Source: godotengine/godot

Godot version:

3.2.1

OS/device including version:

iPhone 7 Plus
iOS 13.5.1

Issue description:

I have test this bbcode in Mac and Android, it can open the mail app or go to the url when click on it, however, on iOS, when clicked, nothing happened.
[center][url=mailto:[email protected]]Contact Us[/url][/center]

[center][url=https://myurl.com]go to[/url][/center]

Steps to reproduce:

Minimal reproduction project:

bug ios porting

Most helpful comment

After digging some more I've found out that the only reason UIScrollView works correctly or more like UIView expected to behave is iOS's private UIScrollViewDelayedTouchesBeganGestureRecognizer class which seems to be responsible for sending touches to UIScrollView.
So I've came with implementation of something similar: https://github.com/godotengine/godot/commit/8acbd90b5f87daea9c27f924aed521905244ea22
But I'm not sure which is better - using custom gesture recognizer or making GLView a subclass of UIScrollView

All 11 comments

@alexzheng could you please confirm that you can reproduce your issue with this repo? https://github.com/naithar/gd_richedit_test
I've tested it on Windows, MacOS and iOS and it works without an issue.

gd_richedit_test-master.zip

It works.

However, when I add more contents and scrolled the contents, it become extremely hard or impossible to open the url on iOS.

@alexzheng I've updated the repo so now it has your code, could you please check it?

For me the behavior on MacOS and iOS is still the same - while scrolling by code is enabled clicking or taping on the link does not lead to browser or mail app. And it doesn't matter where scrolling code is called in _process or _physics_process

The behavior on Windows is not consistent - sometimes it works, sometimes it doesn't, even double clicking.

Enabling a timeout allows tapping to work the same on all devices that I've tested it on, but I'm not really sure how good of a workaround it is.

My Godot release is 3.2.1

For me, While scrolling, on Mac it can open the url, but on iOS device, it can not.

In my original project, I use something like your timer to stop scrolling when tap down.

func _input(event: InputEvent) -> void:
if event is InputEventScreenTouch:
set_physics_process(not event.pressed)
set_process(not event.pressed)

It works on your project, but the ui of my project is a little more complicated, and the url can be opened only on Mac and Android.

The url on my project can be opened even on iPhone Simulator, but on iOS device, it failed to open.

I have set get_v_scroll().step = 0, That cause the url can not be opened.

So, the behavior of RichTextLabel is not consistent on different platforms.

The behavior of RichTextEdit itself is seems to be pretty much consistent across the platforms. This is the part of the code responsible for url clicking: Link
The problem seems to be in touch handling difference. iOS queues its touches while Android seems to be firing them right away: iOS / Android

So basically the problem is that iOS fires touchesEnded: with some delay after touchesBegan: is. And before touchesEnded: fires the game manages to draw one or multiple frames which reset scroll_updated in RichTextLabel instance.
Removing touches queue to fire touches immediately or switching to gesture recognizers for iOS didn't solve the problem for me. The thing that helped is lowering physics and ingame fps, but it's hardly the way to go.
The other problem is that simple tapping fired touchesMoved: which should not have happened, because it creates InputEventScreenDrag event when it shouldn't.

Switching UIView to UIScrollView at this line: https://github.com/godotengine/godot/blob/b0eca5828ccd3a5c07b77e82e567c45937de9056/platform/iphone/gl_view.h#L40 seems to be fixing both touchesEnded:/touchesBegan: delay and touchesMoved: being called on simple tap

After digging some more I've found out that the only reason UIScrollView works correctly or more like UIView expected to behave is iOS's private UIScrollViewDelayedTouchesBeganGestureRecognizer class which seems to be responsible for sending touches to UIScrollView.
So I've came with implementation of something similar: https://github.com/godotengine/godot/commit/8acbd90b5f87daea9c27f924aed521905244ea22
But I'm not sure which is better - using custom gesture recognizer or making GLView a subclass of UIScrollView

Was this page helpful?
0 / 5 - 0 ratings