shadowblip / opengamepadui Goto Github PK
View Code? Open in Web Editor NEWOpen source gamepad-native game launcher and overlay
Home Page: https://opengamepadui.readthedocs.io
License: GNU General Public License v3.0
Open source gamepad-native game launcher and overlay
Home Page: https://opengamepadui.readthedocs.io
License: GNU General Public License v3.0
We need a user-friendly first run interface that will allow a user to configure the environment. Possible options include:
Currently all the new CardUI button elements do not support mouse click/touch events, making the interface only interactable through gamepad or keyboard. These UI elements should support mouse click/touch events.
Currently pressing the help button in the QAM is not implemented.
Users should be able to override and customize Library item launch parameters. E.g. allow setting custom environment variables, arguments, etc.
We should have a UI in our settings menu to manage plugins. We should be able to:
Xlib can allow us to send key/mouse events
There appears to be no connection to the network while in the dedicated session. Because of this I am unable to:
Users should be able to download/install Proton and ProtonGE as new versions are released. We should include interfaces for plugins to poll for configured versions and set their library items to a user selected proton version, or default to the globally set version from this Interface.
I have seen with some automated builds that some exported properties that were set in scenes don't carry over.
We currently rely on tools like xprop
and xwininfo
to retrieve and set XAtoms to tell Gamescope that OpenGamepadUI is an overlay, and where input focus should be. To remove these tools as a dependency, we should add these methods as a GDExtension and directly use the c++ library. Godot already relies on X11/Xatom.h, so it should be straightforward to expose these methods to GDScript.
We need to implement an on-screen keyboard to allow users to input text in-game and in menus.
For sending keyboard input to games, I know that xdotool
supports this functionality until we can implement the methods natively using GDExtension.
Currently pressing the notification button in the QAM doesn't do anything.
We're currently using libevdev to intercept gamepad input and direct it to a virtual gamepad. As a result, we should be able to allow users to customize their controller mappings, send virtual keypresses, etc.
We should create a "game launching" scene that we can show when we just launch a game and we're still waiting to find its window id.
Per #1
Building fails and throws a ton of errors using either the Makefile or directly invoking a headless godot build.
Building on the target machine (Steam Deck) over ssh. Using newest Godot4 beta6 from AUR. Gamescope installed via pacman. Freshly cloned main branch as working directory.
Minor issue, but Makefile uses non-standard fixed paths to godot4 and gamescope binaries, so those needed to be modified to use system paths.
building invoked using both make build
and directly using godot4 --headless --export "Linux"
(per godot4 documentation) as well as trying godot4 --headless --export "Linux/X11"
. Seems to be the same issues in any case.
Was only able to get it to build after repeatedly opening the project in the GUI editor :P
The LaunchManager
should keep track and persist recently launched games and play times. This will allow us to display the most recently played games on the home menu.
Currently OpenGamepadUI doesn't provide an API that can allow Library plugins to prompt the user where they would like games to be installed (e.g. installed on SD card vs internal disk). We should provide an API interface to allow users to select where to install games. Standardizing this interface could be difficult as different library providers may have different ways of storing games. At very least, we should give Library plugins an optional content box where they can populate an interface to select storage.
Godot supports localization. We should implement it so OpenGamepadUI can be run in different languages.
We should create a MetadataProvider
interface to allow pulling and showing metadata for individual games such as game description, screenshots, videos, trailers, tags, etc. This information can be shown on the game launch menu.
I have a cool thing I made, Frontloader, and this would be the perfect kind of thing to use with it. https://github.com/EmuDeck/Frontloader
Hey dude,
I spent a little time today getting the main branch running. Already had both X11 and sway installed, then grabbed godot4-b6 from AUR, so those pull in their own dependencies, but opengamepad-ui cannot, nor does it list what it relies on.
From what I can see it looks like it needs wayland, gamescope, X11, xorg-xwayland, xcb, and probably others? I'm also assuming that it cannot be built with Godot < v4.0? Can we get a list of requirements?
Also, I don't have much experience with Godot, but is there a way to import assets and build this headlessly? I do pretty much everything over ssh, but godot refuses to build the project unless I run the editor in a GUI session even with the --headless
option. I get a mountain of errors about assets need to be imported in the editor. After opening and closing the editor a few times it finally decided to import. Seems like there should be a way to automate that headlessly.
I'd really rather not ever need to run a huge GUI IDE just to build a binary if possible, haha
OGUI has the concept of BoxArt Providers
to provide box art for a particular library item. We should allow users to select which box art provider they want to use for a particular game.
Currently BoxArtProvider
has just one method for fetching the boxart for a given LibraryItem
in a certain format. We should add a method that allows boxart providers to cycle through multiple available artworks for a given library item.
Godot already supports theming. We should define the default theme and use that everywhere instead of doing per-element overrides. Then we can also add a settings menu to select different themes.
Detecting when games close is complex. Normally, when we launch a non-Steam game, we get the process ID of the thing we just launched, and can check if that PID has died. Easy peasy:
gamescope (pid 10)
\---- opengamepadui (pid 11) - { I launched you with pid 12! }
\---- game (pid 12)
Steam, however, doesn't make it easy for us. When you launch a Steam game, it launches a "steam launcher" script, where its whole job is to start up Steam and then die.
gamescope (pid 10)
\---- opengamepadui (pid 11) - { I launched you with pid 12! }
\---- steam (pid 12) - { Ok, time to die! }
\---- steam-for-real (pid 13)
This has the fantastic consequence of orphaning the real Steam process.
gamescope (pid 10)
\---- opengamepadui (pid 11)
\---- (defunct)
\---- steam-for-real (pid 13)
This is a common technique called double-fork, where a process will fork itself, and then die. It's a way to try and daemonize a process. When a process gets orphaned, the init process (pid 1) or a SUBREAPER becomes its new parent. In this case, gamescope takes the poor orphan in.
gamescope (pid 10)
|---- opengamepadui (pid 11) - { Did the game just die? }
\ \---- (defunct)
\--- steam-for-real (pid 13)
\---- game (pid 14)
We might actually be able to use subreaper ourselves to make Steam re-parent to us, which might make things a bit easier. But right now, to OGUI, it looks like the game just died. Luckily we have a few tricks to find where Steam went. Whenever we spawn a process, it also has a PGID or process group ID! We can use that to determine what decedents might still be hanging around.
gamescope (pid 10)
|---- opengamepadui (pid 11) - { Hey wait, you still have children around! }
\ \---- (defunct) (pid: 12, pgid: 12)
\--- steam-for-real (pid 13, pgid: 12)
\---- game (pid 14, pgid: 12)
Great! Now we can find the decedents of our process we launched. If we want to exit a game, we can just kill all the decedents. That brings us to our next problem: Steam doesn't like to die. If game
crashes or exits normally, Steam sticks around. There's not a super robust way to detect what the real game is.
gamescope (pid 10)
|---- opengamepadui (pid 11) - { Hmmm, not sure if game, or just steam processes... }
\ \---- (defunct)
\--- steam-for-real (pid 13, pgid: 12)
\---- (defunct)
There's a few things we could try:
STEAM_GAME
window properties.
???
We should have a UI for a quick access menu that users can use in-game to adjust common and game-specific settings.
OpengamepadUI will crash if your library is still loading and you swtich from "all games" to another tab. Unsure if this is a LibraryManager bug or a opengamepadui-steam bug.
================================================================
handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.0.rc1.official (8843d9ad347e5c3be5130153aeecdf48e4fe5a14)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /usr/lib/libc.so.6(+0x38f50) [0x7fbdd7874f50] (??:0)
[2] /usr/bin/godot4() [0x125fb52] (??:0)
[3] /usr/bin/godot4() [0x117698f] (??:0)
[4] /usr/bin/godot4() [0x4555f6b] (??:0)
[5] /usr/bin/godot4() [0x438ee84] (??:0)
[6] /usr/bin/godot4() [0x458a04a] (??:0)
[7] /usr/bin/godot4() [0x2dcd838] (??:0)
[8] /usr/bin/godot4() [0x458a04a] (??:0)
[9] /usr/bin/godot4() [0x2dc6b61] (??:0)
[10] /usr/bin/godot4() [0xea091b] (??:0)
[11] /usr/bin/godot4() [0x45590e6] (??:0)
[12] /usr/bin/godot4() [0x458ba8e] (??:0)
[13] /usr/bin/godot4() [0x124ef78] (??:0)
[14] /usr/bin/godot4() [0x117698f] (??:0)
[15] /usr/bin/godot4() [0x2b6f05c] (??:0)
[16] /usr/bin/godot4() [0x2bcf6c2] (??:0)
[17] /usr/bin/godot4() [0x2bcffab] (??:0)
[18] /usr/bin/godot4() [0x2bece25] (??:0)
[19] /usr/bin/godot4() [0xe7e58a] (??:0)
[20] /usr/bin/godot4() [0x431cf34] (??:0)
[21] /usr/bin/godot4() [0x431e055] (??:0)
[22] /usr/bin/godot4() [0xe7eee7] (??:0)
[23] /usr/bin/godot4() [0xdf2252] (??:0)
[24] /usr/lib/libc.so.6(+0x23790) [0x7fbdd785f790] (??:0)
[25] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7fbdd785f84a] (??:0)
[26] /usr/bin/godot4() [0xe1234e] (??:0)
-- END OF BACKTRACE --
================================================================
connection handler failed
Traceback (most recent call last):
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 968, in transfer_data
message = await self.read_message()
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 1038, in read_message
frame = await self.read_data_frame(max_size=self.max_size)
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 1113, in read_data_frame
frame = await self.read_frame(max_size)
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 1170, in read_frame
frame = await Frame.read(
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/framing.py", line 69, in read
data = await reader(2)
File "/usr/lib/python3.10/asyncio/streams.py", line 705, in readexactly
raise exceptions.IncompleteReadError(incomplete, n)
asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/server.py", line 236, in handler
await self.ws_handler(self)
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/server.py", line 1175, in _ws_handler
return await cast(
File "/home/blip/.local/share/opengamepadui/scripts/steam/server.py", line 146, in main
async for message in websocket:
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 497, in __aiter__
yield await self.recv()
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 568, in recv
await self.ensure_open()
File "/home/blip/.pex/installed_wheels/a1b6b65cec48f201c6eec25be6abbee9fd40c9bd1892e2f4d4890f51183dd672/websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl/websockets/legacy/protocol.py", line 944, in ensure_open
raise self.connection_closed_exc()
websockets.exceptions.ConnectionClosedError: no close frame received or sent
https://aur.archlinux.org/packages/opengamepadui-session-gitThe XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Unsupported maximum keycode 708, clipping.
> X11 cannot support keycodes above 255.
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Unsupported maximum keycode 708, clipping.
> X11 cannot support keycodes above 255.
Errors from xkbcomp are not fatal to the X server
Errors from xkbcomp are not fatal to the X server
^Cgamescope: received kill signal, terminating!
xwm: Lost connection to the X11 server 0
xwm: X11 I/O error
We need a way to change the default language of the interface based on user selection and/or OS settings.
Noted in PR #17 , we should remove the state popping logic from InputManager and let each menu decide how to handle the back button.
We should implement search functionality in all states that support it.
Per #17 (comment) we should look into taking the global state management out of Input Manager and allow each menu to handle its own logic for back.
One of the great features that Steam has is the ability for the community to create and share gamepad profiles. This would be a great feature for OpenGamepadUI, but may be challenging to implement. Valve stores these profiles and shares them using their own server infrastructure, of which we do not have for OpenGamepadUI.
A solution could be to have a GitHub repository that users could make pull requests to with per-game profiles, similar to how the current plugin store is implemented.
Some benefits would be:
Some problems with this solution are:
Another potential solution could be trying to use peer-to-peer sharing with something like IPFS to share custom profiles.
Some benefits would be:
Some problems with this solution:
Currently touch-and-drag is supported to scroll through scroll containers, but only if you touch somewhere inside a scroll container that doesn't have a UI element. This makes touch scrolling a really bad experience.
Touch scroll events should be detected and passed to the scroll container.
Various launchers sometimes leave processes lying around. We should have a process manager that allows us to view and kill processes.
OGUI has the concept of Library Providers
. These are systems which can provide a LibraryLaunchItem
which describes how to launch a particular game. Sometimes you may have multiple Library providers that can provide a way to launch the same game. We should allow the user to configure which Library provider should be used to launch a particular game.
We should define an interface that will query ProtonDB when provided a title and return basic information to the requesting plugin. It should also support iconography for platinum/gold/silver/borked/untested.
We should be able to use "x" for backspace, left trigger for shift, etc.
When on any menu other than home (e.g. Library, Settings, etc.), and you open up the main menu or QAM, the home menu is shown behind the current menu:
This is due to how VisibilityManager
is implemented, which has a visible_during
property that allows menus to be visible when the main menu, qam, and OSK are being shown.
One potential way this could be fixed could be to use a separate StateMachine
for these overlay menus (main menu, qam, and OSK). We would just need some mechanism to re-focus the current menu when no states remain in the overlay menu state machine.
OpenCloudSaves is an open source save game sync manager. We should try to integrate it as either part of the core or as a plugin.
When running Steam games, it's impossible to open the Steam overlay due to OpenGamepadUI gamepad interception. We should provide an option in the UI for users to send a guide button press to the running game to allow opening the Steam overlay (or other 3rd party overlays).
We should create a new repository that will act as the index for the plugin store. It should contain a JSON file that acts as the plugin store registry that points to available plugins.
It should look something like this:
{
"plugins": [
{
"plugin.id": "flathub",
"plugin.name": "FlatHub",
"plugin.version": "1.0.0",
"plugin.min-api-version": "1.0.0",
"plugin.link": "https://github.com/ShadowBlip/OpenGamepadUI-flathub-plugin",
"plugin.source": "https://github.com/ShadowBlip/OpenGamepadUI-flathub-plugin",
"plugin.description": "FlatHub frontend for OpenGamepadUI",
"plugin.archive": "https://github.com/ShadowBlip/OpenGamepadUI-flathub-plugin/refs/download/flathub-plugin-1.0.0.zip",
"plugin.sha256": "b7bef0ae7dc06be5c1b7a8f35ff57ef932f3a1c7a1e8fe5aaf97c3d73d84edf2"
"store.tags": ["flatpak", "flathub"],
"store.images": ["https://path/to/image.png"],
"author.name": "William Edwards",
"author.email": "[email protected]",
}
]
}
Users can add their plugin to the store by opening a pull request to this repo, and can be added after review and verification.
It would be nice to have the ability to use SDL2 mappings for unusual gamepads. Via plugin or a direct implementation. Here is what I'm referring to btw. Not to be confused with another project with a similar name.
We need to implement a settings manager and user interface to load and save user settings. This should probably be a singleton which all nodes can access for global settings.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.