summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp5
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp5
-rw-r--r--platform/linuxbsd/joypad_linux.cpp48
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp44
-rw-r--r--platform/linuxbsd/os_linuxbsd.h3
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp3
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp126
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h6
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp3
9 files changed, 218 insertions, 25 deletions
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index b45b7e676d..6dfa8ed93c 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -138,6 +138,11 @@ FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
#else
unsupported = false;
#endif
+
+ if (unsupported) {
+ return;
+ }
+
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index 78f2337599..cf179b5735 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -141,6 +141,11 @@ FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
#else
unsupported = false;
#endif
+
+ if (unsupported) {
+ return;
+ }
+
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index 5c623b8ba2..a9725fff2e 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -32,6 +32,8 @@
#include "joypad_linux.h"
+#include "core/os/os.h"
+
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -72,6 +74,26 @@ 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(Input *in) {
#ifdef UDEV_ENABLED
#ifdef SOWRAP_ENABLED
@@ -80,17 +102,25 @@ JoypadLinux::JoypadLinux(Input *in) {
#else
int dylibloader_verbose = 0;
#endif
- use_udev = initialize_libudev(dylibloader_verbose) == 0;
- if (use_udev) {
- if (!udev_new || !udev_unref || !udev_enumerate_new || !udev_enumerate_add_match_subsystem || !udev_enumerate_scan_devices || !udev_enumerate_get_list_entry || !udev_list_entry_get_next || !udev_list_entry_get_name || !udev_device_new_from_syspath || !udev_device_get_devnode || !udev_device_get_action || !udev_device_unref || !udev_enumerate_unref || !udev_monitor_new_from_netlink || !udev_monitor_filter_add_match_subsystem_devtype || !udev_monitor_enable_receiving || !udev_monitor_get_fd || !udev_monitor_receive_device || !udev_monitor_unref) {
- // There's no API to check version, check if functions are available instead.
- use_udev = false;
- print_verbose("JoypadLinux: Unsupported udev library version!");
+ 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 {
+ use_udev = initialize_libudev(dylibloader_verbose) == 0;
+ if (use_udev) {
+ if (!udev_new || !udev_unref || !udev_enumerate_new || !udev_enumerate_add_match_subsystem || !udev_enumerate_scan_devices || !udev_enumerate_get_list_entry || !udev_list_entry_get_next || !udev_list_entry_get_name || !udev_device_new_from_syspath || !udev_device_get_devnode || !udev_device_get_action || !udev_device_unref || !udev_enumerate_unref || !udev_monitor_new_from_netlink || !udev_monitor_filter_add_match_subsystem_devtype || !udev_monitor_enable_receiving || !udev_monitor_get_fd || !udev_monitor_receive_device || !udev_monitor_unref) {
+ // There's no API to check version, check if functions are available instead.
+ use_udev = false;
+ print_verbose("JoypadLinux: Unsupported udev library version!");
+ } else {
+ print_verbose("JoypadLinux: udev enabled and loaded successfully.");
+ }
} else {
- print_verbose("JoypadLinux: udev enabled and loaded successfully.");
+ print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. 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.");
}
#endif
#else
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 11c81be4a9..8d8c8ce27b 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -30,6 +30,7 @@
#include "os_linuxbsd.h"
+#include "core/io/certs_compressed.gen.h"
#include "core/io/dir_access.h"
#include "main/main.h"
#include "servers/display_server.h"
@@ -195,6 +196,10 @@ void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
main_loop = p_main_loop;
}
+String OS_LinuxBSD::get_identifier() const {
+ return "linuxbsd";
+}
+
String OS_LinuxBSD::get_name() const {
#ifdef __linux__
return "Linux";
@@ -490,6 +495,11 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
return true;
}
+ // Match against the specific OS (linux, freebsd, etc).
+ if (p_feature == get_name().to_lower()) {
+ return true;
+ }
+
return false;
}
@@ -1076,6 +1086,40 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
return OK;
}
+String OS_LinuxBSD::get_system_ca_certificates() {
+ String certfile;
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Compile time preferred certificates path.
+ if (!String(_SYSTEM_CERTS_PATH).is_empty() && da->file_exists(_SYSTEM_CERTS_PATH)) {
+ certfile = _SYSTEM_CERTS_PATH;
+ } else if (da->file_exists("/etc/ssl/certs/ca-certificates.crt")) {
+ // Debian/Ubuntu
+ certfile = "/etc/ssl/certs/ca-certificates.crt";
+ } else if (da->file_exists("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem")) {
+ // Fedora
+ certfile = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
+ } else if (da->file_exists("/etc/ca-certificates/extracted/tls-ca-bundle.pem")) {
+ // Arch Linux
+ certfile = "/etc/ca-certificates/extracted/tls-ca-bundle.pem";
+ } else if (da->file_exists("/var/lib/ca-certificates/ca-bundle.pem")) {
+ // openSUSE
+ certfile = "/var/lib/ca-certificates/ca-bundle.pem";
+ } else if (da->file_exists("/etc/ssl/cert.pem")) {
+ // FreeBSD/OpenBSD
+ certfile = "/etc/ssl/cert.pem";
+ }
+
+ if (certfile.is_empty()) {
+ return "";
+ }
+
+ Ref<FileAccess> f = FileAccess::open(certfile, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", vformat("Failed to open system CA certificates file: '%s'", certfile));
+
+ return f->get_as_text();
+}
+
OS_LinuxBSD::OS_LinuxBSD() {
main_loop = nullptr;
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 9423514944..c1e735b0d4 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -96,6 +96,7 @@ protected:
virtual void set_main_loop(MainLoop *p_main_loop) override;
public:
+ virtual String get_identifier() const override;
virtual String get_name() const override;
virtual String get_distribution_name() const override;
virtual String get_version() const override;
@@ -132,6 +133,8 @@ public:
virtual Error move_to_trash(const String &p_path) override;
+ virtual String get_system_ca_certificates() override;
+
OS_LinuxBSD();
~OS_LinuxBSD();
};
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 3d07be1c76..78778a8b56 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -60,6 +60,9 @@
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+// To prevent shadowing warnings
+#undef glGetString
+
struct vendor {
const char *glxvendor = nullptr;
int priority = 0;
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index ac4fbe2068..9506189573 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -186,6 +186,7 @@ bool DisplayServerX11::_refresh_device_info() {
xi.absolute_devices.clear();
xi.touch_devices.clear();
xi.pen_inverted_devices.clear();
+ xi.last_relative_time = 0;
int dev_count;
XIDeviceInfo *info = XIQueryDevice(x11_display, XIAllDevices, &dev_count);
@@ -1205,6 +1206,105 @@ Color DisplayServerX11::screen_get_pixel(const Point2i &p_position) const {
return Color();
}
+Ref<Image> DisplayServerX11::screen_get_image(int p_screen) const {
+ ERR_FAIL_INDEX_V(p_screen, get_screen_count(), Ref<Image>());
+
+ switch (p_screen) {
+ case SCREEN_PRIMARY: {
+ p_screen = get_primary_screen();
+ } break;
+ case SCREEN_OF_MAIN_WINDOW: {
+ p_screen = window_get_current_screen(MAIN_WINDOW_ID);
+ } break;
+ default:
+ break;
+ }
+
+ ERR_FAIL_COND_V(p_screen < 0, Ref<Image>());
+
+ XImage *image = nullptr;
+
+ int event_base, error_base;
+ if (XineramaQueryExtension(x11_display, &event_base, &error_base)) {
+ int xin_count;
+ XineramaScreenInfo *xsi = XineramaQueryScreens(x11_display, &xin_count);
+ if (p_screen < xin_count) {
+ int x_count = XScreenCount(x11_display);
+ for (int i = 0; i < x_count; i++) {
+ Window root = XRootWindow(x11_display, i);
+ XWindowAttributes root_attrs;
+ XGetWindowAttributes(x11_display, root, &root_attrs);
+ if ((xsi[p_screen].x_org >= root_attrs.x) && (xsi[p_screen].x_org <= root_attrs.x + root_attrs.width) && (xsi[p_screen].y_org >= root_attrs.y) && (xsi[p_screen].y_org <= root_attrs.y + root_attrs.height)) {
+ image = XGetImage(x11_display, root, xsi[p_screen].x_org, xsi[p_screen].y_org, xsi[p_screen].width, xsi[p_screen].height, AllPlanes, ZPixmap);
+ break;
+ }
+ }
+ } else {
+ ERR_FAIL_V_MSG(Ref<Image>(), "Invalid screen index: " + itos(p_screen) + "(count: " + itos(xin_count) + ").");
+ }
+ } else {
+ int x_count = XScreenCount(x11_display);
+ if (p_screen < x_count) {
+ Window root = XRootWindow(x11_display, p_screen);
+
+ XWindowAttributes root_attrs;
+ XGetWindowAttributes(x11_display, root, &root_attrs);
+
+ image = XGetImage(x11_display, root, root_attrs.x, root_attrs.y, root_attrs.width, root_attrs.height, AllPlanes, ZPixmap);
+ } else {
+ ERR_FAIL_V_MSG(Ref<Image>(), "Invalid screen index: " + itos(p_screen) + "(count: " + itos(x_count) + ").");
+ }
+ }
+
+ Ref<Image> img;
+ if (image) {
+ int width = image->width;
+ int height = image->height;
+
+ Vector<uint8_t> img_data;
+ img_data.resize(height * width * 4);
+
+ uint8_t *sr = (uint8_t *)image->data;
+ uint8_t *wr = (uint8_t *)img_data.ptrw();
+
+ if (image->bits_per_pixel == 24 && image->red_mask == 0xff0000 && image->green_mask == 0x00ff00 && image->blue_mask == 0x0000ff) {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ wr[(y * width + x) * 4 + 0] = sr[(y * width + x) * 3 + 2];
+ wr[(y * width + x) * 4 + 1] = sr[(y * width + x) * 3 + 1];
+ wr[(y * width + x) * 4 + 2] = sr[(y * width + x) * 3 + 0];
+ wr[(y * width + x) * 4 + 3] = 255;
+ }
+ }
+ } else if (image->bits_per_pixel == 24 && image->red_mask == 0x0000ff && image->green_mask == 0x00ff00 && image->blue_mask == 0xff0000) {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ wr[(y * width + x) * 4 + 0] = sr[(y * width + x) * 3 + 2];
+ wr[(y * width + x) * 4 + 1] = sr[(y * width + x) * 3 + 1];
+ wr[(y * width + x) * 4 + 2] = sr[(y * width + x) * 3 + 0];
+ wr[(y * width + x) * 4 + 3] = 255;
+ }
+ }
+ } else if (image->bits_per_pixel == 32 && image->red_mask == 0xff0000 && image->green_mask == 0x00ff00 && image->blue_mask == 0x0000ff) {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ wr[(y * width + x) * 4 + 0] = sr[(y * width + x) * 4 + 2];
+ wr[(y * width + x) * 4 + 1] = sr[(y * width + x) * 4 + 1];
+ wr[(y * width + x) * 4 + 2] = sr[(y * width + x) * 4 + 0];
+ wr[(y * width + x) * 4 + 3] = 255;
+ }
+ }
+ } else {
+ XFree(image);
+ ERR_FAIL_V_MSG(Ref<Image>(), vformat("XImage with RGB mask %x %x %x and depth %d is not supported.", image->red_mask, image->green_mask, image->blue_mask, image->bits_per_pixel));
+ }
+ img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, img_data);
+ XFree(image);
+ }
+
+ return img;
+}
+
float DisplayServerX11::screen_get_refresh_rate(int p_screen) const {
_THREAD_SAFE_METHOD_
@@ -2724,8 +2824,8 @@ void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, Cu
XcursorImageDestroy(cursor_image);
} else {
// Reset to default system cursor
- if (img[p_shape]) {
- cursors[p_shape] = XcursorImageLoadCursor(x11_display, img[p_shape]);
+ if (cursor_img[p_shape]) {
+ cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_img[p_shape]);
}
CursorShape c = current_cursor;
@@ -3497,8 +3597,8 @@ void DisplayServerX11::_window_changed(XEvent *event) {
// Query display server about a possible new window state.
wd.fullscreen = _window_fullscreen_check(window_id);
- wd.minimized = _window_minimize_check(window_id);
- wd.maximized = _window_maximize_check(window_id, "_NET_WM_STATE");
+ wd.maximized = _window_maximize_check(window_id, "_NET_WM_STATE") && !wd.fullscreen;
+ wd.minimized = _window_minimize_check(window_id) && !wd.fullscreen && !wd.maximized;
// Readjusting the window position if the window is being reparented by the window manager for decoration
Window root, parent, *children;
@@ -5359,7 +5459,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
for (int i = 0; i < CURSOR_MAX; i++) {
cursors[i] = None;
- img[i] = nullptr;
+ cursor_img[i] = nullptr;
}
XInitThreads(); //always use threads
@@ -5716,8 +5816,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
"question_arrow"
};
- img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
- if (!img[i]) {
+ cursor_img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
+ if (!cursor_img[i]) {
const char *fallback = nullptr;
switch (i) {
@@ -5755,7 +5855,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
fallback = "bd_double_arrow";
break;
case CURSOR_MOVE:
- img[i] = img[CURSOR_DRAG];
+ cursor_img[i] = cursor_img[CURSOR_DRAG];
break;
case CURSOR_VSPLIT:
fallback = "sb_v_double_arrow";
@@ -5768,11 +5868,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
break;
}
if (fallback != nullptr) {
- img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size);
+ cursor_img[i] = XcursorLibraryLoadImage(fallback, cursor_theme, cursor_size);
}
}
- if (img[i]) {
- cursors[i] = XcursorImageLoadCursor(x11_display, img[i]);
+ if (cursor_img[i]) {
+ cursors[i] = XcursorImageLoadCursor(x11_display, cursor_img[i]);
} else {
print_verbose("Failed loading custom cursor: " + String(cursor_file[i]));
}
@@ -5911,8 +6011,8 @@ DisplayServerX11::~DisplayServerX11() {
if (cursors[i] != None) {
XFreeCursor(x11_display, cursors[i]);
}
- if (img[i] != nullptr) {
- XcursorImageDestroy(img[i]);
+ if (cursor_img[i] != nullptr) {
+ XcursorImageDestroy(cursor_img[i]);
}
}
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index e8e0680c14..fd3a5dccfa 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -119,8 +119,7 @@ typedef struct _xrr_monitor_info {
#undef CursorShape
class DisplayServerX11 : public DisplayServer {
- //No need to register, it's platform-specific and nothing is added
- //GDCLASS(DisplayServerX11, DisplayServer)
+ // No need to register with GDCLASS, it's platform-specific and nothing is added.
_THREAD_SAFE_CLASS_
@@ -307,7 +306,7 @@ class DisplayServerX11 : public DisplayServer {
const char *cursor_theme = nullptr;
int cursor_size = 0;
- XcursorImage *img[CURSOR_MAX];
+ XcursorImage *cursor_img[CURSOR_MAX];
Cursor cursors[CURSOR_MAX];
Cursor null_cursor;
CursorShape current_cursor = CURSOR_ARROW;
@@ -413,6 +412,7 @@ public:
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Color screen_get_pixel(const Point2i &p_position) const override;
+ virtual Ref<Image> screen_get_image(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
#if defined(DBUS_ENABLED)
virtual void screen_set_keep_on(bool p_enable) override;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index ee767dfa80..1e579c9f01 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -44,6 +44,9 @@
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display *, GLXFBConfig, GLXContext, Bool, const int *);
+// To prevent shadowing warnings
+#undef glXCreateContextAttribsARB
+
struct GLManager_X11_Private {
::GLXContext glx_context;
};