-
-
Save geekley/5e6daf62d2e86b566c4886f20b604d21 to your computer and use it in GitHub Desktop.
| # Public domain, as per The Unlicense. NO WARRANTY. See https://unlicense.org | |
| extends Node | |
| ## Solves a [url=https://github.com/godotengine/godot/issues/59250]bug[/url] where touchpad devices | |
| ## can be detected as a joypad. | |
| ## | |
| ## This script should be autoloaded in the project settings. | |
| ## This is merely a workaround, not intended for use in production code. | |
| func _enter_tree() -> void: | |
| _connect_joy_check() | |
| queue_free() | |
| static func _connect_joy_check() -> void: | |
| var _Self: GDScript = (func() -> void:).get_object() as GDScript | |
| if Input.joy_connection_changed.connect(Callable(_Self, joy_check.get_method())) != OK: | |
| assert(false) | |
| pass | |
| ## Validates a joypad connection. Called for every joypad device connected. | |
| ## Device names matching the pattern will be disabled (remapped to an empty mapping). | |
| static func joy_check(device: int, connected: bool) -> void: | |
| if not connected: | |
| return | |
| var device_name: String = Input.get_joy_name(device) | |
| # Uncomment the line below to debug problematic devices: | |
| # print('Connected device ', device, ': ', device_name) | |
| if not is_banned(device_name): | |
| return | |
| # If name has matched any banned word, this joypad device should be ignored. | |
| var guid: String = Input.get_joy_guid(device) | |
| # Disable input by mapping no axes or buttons. Will ignore future joypad input from this device. | |
| var mapping: String = guid + ',' + device_name.replace(',', '') | |
| Input.add_joy_mapping(mapping, true) | |
| # Past input events might have been sent. Reset this device sending 0 on all SDL axes and buttons. | |
| for axis: JoyAxis in range(JOY_AXIS_SDL_MAX) as Array[JoyAxis]: | |
| var event: InputEventJoypadMotion = InputEventJoypadMotion.new() | |
| event.device = device | |
| event.axis = axis | |
| Input.parse_input_event(event) | |
| for button_index: JoyButton in range(JOY_BUTTON_SDL_MAX) as Array[JoyButton]: | |
| var event: InputEventJoypadButton = InputEventJoypadButton.new() | |
| event.device = device | |
| event.button_index = button_index | |
| Input.parse_input_event(event) | |
| prints('Ignoring joypad device:', mapping) # you can comment out or remove this line | |
| ## True only if the device name contains a banned word, case-insensitively. | |
| ## A banned substring only matches if it's guaranteed to be a separate word. | |
| static func is_banned(device_name: String) -> bool: | |
| for word: String in banned_words: | |
| var i: int = device_name.findn(word) | |
| if i < 0: | |
| continue # this banned word was not found as a substring | |
| if i > 0 and not is_ascii_non_letter(device_name[i - 1]): | |
| continue # substring found, but it's not guaranteed to start a word | |
| var j: int = i + word.length() | |
| if j < device_name.length() and not is_ascii_non_letter(device_name[j]): | |
| continue # it starts a word, but it's not guaranteed to also end it | |
| return true # substring found and guaranteed to form a separate word | |
| return false # no banned word found | |
| ## True only if the character is ASCII and not a letter. | |
| static func is_ascii_non_letter(c: String) -> bool: | |
| return c.unicode_at(0) < 128 and not (c >= 'a' and c <= 'z' or c >= 'A' and c <= 'Z') | |
| ## List of words forbidden in joypad names. | |
| const banned_words: PackedStringArray = [ | |
| 'touchpad', 'trackpad', 'clickpad', 'synaptics', | |
| 'mouse', | |
| 'pen', 'finger', # drawing tablets | |
| 'keyboard', | |
| 'led', | |
| ] |
Well, neither this list nor this repo's files include this word, so I guess I'll consider it safe to include. I'll update it, thanks @MultisampledNight!
If possible, it would very helpful if you can please confirm it doesn't break accessing multi-touch input as such if desired - e.g. are InputEventScreenTouch and similar events still received?
Btw, if anyone else finds any other devices as false positives or false negatives, please let me know by commenting here too.
I opened a PR to fix the issue in the engine:
Thanks for providing the list of banned words 🙂
Revised to match the PR godotengine/godot#101260, see also godotengine/godot#59250 (comment)
Adding synaptics as a banned word, since the device name no longer includes "touchpad" after a system update on Linux.
Are you using Linux? A recent (kernel?) update changed the name on the touchpad device in my laptop. [...]
For me, the device name wasSynPS/2 Synaptics TouchPad, but becameSynaptics TM2768-001.
Hi! On the Acer Spin 5 on NixOS,
Wacom HID 495F Fingeris also a joypad registered by godot, which is actually the touchscreen. I guess it might make sense to ban the wordfingeras well?