Skip to content

Commit

Permalink
Linux: Don't use udev for joypad hotloading when running in a sandbox
Browse files Browse the repository at this point in the history
udev doesn't work in sandboxes, notably the new Steam container runtime
as found notably on the Steam Deck, and in Flatpak/Snap packages.

Like SDL does, when we detect such a containerized environment, we fall
back to parsing `/dev/input` directly.
See smcv's comments in godotengine#76879 for details.

Fixes godotengine#76879.

(cherry picked from commit 788cb74)
  • Loading branch information
akien-mga committed May 12, 2023
1 parent 3762fe3 commit 8a23fa4
Showing 1 changed file with 34 additions and 4 deletions.
38 changes: 34 additions & 4 deletions platform/x11/joypad_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include "joypad_linux.h"

#include "core/os/os.h"

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
Expand Down Expand Up @@ -77,13 +79,41 @@ void JoypadLinux::Joypad::reset() {
events.clear();
}

// This function is derived from SDL:
// https://github.com/libsdl-org/SDL/blob/main/src/core/linux/SDL_sandbox.c#L28-L45
static bool detect_sandbox() {
if (access("/.flatpak-info", F_OK) == 0) {
return true;
}

// For Snap, we check multiple variables because they might be set for
// unrelated reasons. This is the same thing WebKitGTK does.
if (OS::get_singleton()->has_environment("SNAP") && OS::get_singleton()->has_environment("SNAP_NAME") && OS::get_singleton()->has_environment("SNAP_REVISION")) {
return true;
}

if (access("/run/host/container-manager", F_OK) == 0) {
return true;
}

return false;
}

JoypadLinux::JoypadLinux(InputDefault *in) {
#ifdef UDEV_ENABLED
use_udev = initialize_libudev() == 0;
if (use_udev) {
print_verbose("JoypadLinux: udev enabled and loaded successfully.");
if (detect_sandbox()) {
// Linux binaries in sandboxes / containers need special handling because
// libudev doesn't work there. So we need to fallback to manual parsing
// of /dev/input in such case.
use_udev = false;
print_verbose("JoypadLinux: udev enabled, but detected incompatible sandboxed mode. Falling back to /dev/input to detect joypads.");
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
use_udev = initialize_libudev() == 0;
if (use_udev) {
print_verbose("JoypadLinux: udev enabled and loaded successfully.");
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
}
}
#else
print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
Expand Down

0 comments on commit 8a23fa4

Please sign in to comment.