diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp index 513499c1759..81f7e53fb13 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.cpp +++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp @@ -49,6 +49,7 @@ #define BUS_OBJECT_NAME "org.freedesktop.portal.Desktop" #define BUS_OBJECT_PATH "/org/freedesktop/portal/desktop" +#define BUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" #define BUS_INTERFACE_SETTINGS "org.freedesktop.portal.Settings" #define BUS_INTERFACE_FILE_CHOOSER "org.freedesktop.portal.FileChooser" @@ -387,6 +388,61 @@ bool FreeDesktopPortalDesktop::file_chooser_parse_response(DBusMessageIter *p_it return true; } +bool FreeDesktopPortalDesktop::_is_interface_supported(const char *p_iface) { + bool supported = false; + DBusError err; + dbus_error_init(&err); + DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + } else { + DBusMessage *message = dbus_message_new_method_call(BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE_PROPERTIES, "Get"); + if (message) { + const char *name_space = p_iface; + const char *key = "version"; + dbus_message_append_args( + message, + DBUS_TYPE_STRING, &name_space, + DBUS_TYPE_STRING, &key, + DBUS_TYPE_INVALID); + DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 250, &err); + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + } else if (reply) { + DBusMessageIter iter; + if (dbus_message_iter_init(reply, &iter)) { + DBusMessageIter iter_ver; + dbus_message_iter_recurse(&iter, &iter_ver); + dbus_uint32_t ver_code; + dbus_message_iter_get_basic(&iter_ver, &ver_code); + print_verbose(vformat("PortalDesktop: %s version %d detected.", p_iface, ver_code)); + supported = true; + } + dbus_message_unref(reply); + } + dbus_message_unref(message); + } + dbus_connection_unref(bus); + } + return supported; +} + +bool FreeDesktopPortalDesktop::is_file_chooser_supported() { + static int supported = -1; + if (supported == -1) { + supported = _is_interface_supported(BUS_INTERFACE_FILE_CHOOSER); + } + return supported; +} + +bool FreeDesktopPortalDesktop::is_settings_supported() { + static int supported = -1; + if (supported == -1) { + supported = _is_interface_supported(BUS_INTERFACE_SETTINGS); + } + return supported; +} + Error FreeDesktopPortalDesktop::file_dialog_show(DisplayServer::WindowID p_window_id, const String &p_xid, const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, DisplayServer::FileDialogMode p_mode, const Vector &p_filters, const TypedArray &p_options, const Callable &p_callback, bool p_options_in_cb) { if (unsupported) { return FAILED; diff --git a/platform/linuxbsd/freedesktop_portal_desktop.h b/platform/linuxbsd/freedesktop_portal_desktop.h index 330004758af..de14021cfbf 100644 --- a/platform/linuxbsd/freedesktop_portal_desktop.h +++ b/platform/linuxbsd/freedesktop_portal_desktop.h @@ -85,6 +85,7 @@ private: String theme_path; Callable system_theme_changed; void _system_theme_changed_callback(); + bool _is_interface_supported(const char *p_iface); static void _thread_monitor(void *p_ud); @@ -93,10 +94,16 @@ public: ~FreeDesktopPortalDesktop(); bool is_supported() { return !unsupported; } + bool is_file_chooser_supported(); + bool is_settings_supported(); + + // org.freedesktop.portal.FileChooser methods. Error file_dialog_show(DisplayServer::WindowID p_window_id, const String &p_xid, const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, DisplayServer::FileDialogMode p_mode, const Vector &p_filters, const TypedArray &p_options, const Callable &p_callback, bool p_options_in_cb); void process_file_dialog_callbacks(); + // org.freedesktop.portal.Settings methods. + // Retrieve the system's preferred color scheme. // 0: No preference or unknown. // 1: Prefer dark appearance. diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 5f7bf98a61f..6d7d2125c68 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -220,7 +220,7 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const { case FEATURE_NATIVE_DIALOG_FILE: case FEATURE_NATIVE_DIALOG_FILE_EXTRA: case FEATURE_NATIVE_DIALOG_FILE_MIME: { - return true; + return (portal_desktop && portal_desktop->is_supported() && portal_desktop->is_file_chooser_supported()); } break; #endif @@ -282,10 +282,13 @@ void DisplayServerWayland::tts_stop() { #ifdef DBUS_ENABLED bool DisplayServerWayland::is_dark_mode_supported() const { - return portal_desktop->is_supported(); + return portal_desktop && portal_desktop->is_supported() && portal_desktop->is_settings_supported(); } bool DisplayServerWayland::is_dark_mode() const { + if (!is_dark_mode_supported()) { + return false; + } switch (portal_desktop->get_appearance_color_scheme()) { case 1: // Prefers dark theme. diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 18500f70196..2cd2afe1a9e 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -137,30 +137,40 @@ bool DisplayServerX11::has_feature(Feature p_feature) const { case FEATURE_WINDOW_TRANSPARENCY: //case FEATURE_HIDPI: case FEATURE_ICON: -#ifdef DBUS_ENABLED - case FEATURE_NATIVE_DIALOG_FILE: - case FEATURE_NATIVE_DIALOG_FILE_EXTRA: - case FEATURE_NATIVE_DIALOG_FILE_MIME: -#endif - //case FEATURE_NATIVE_DIALOG: - //case FEATURE_NATIVE_DIALOG_INPUT: //case FEATURE_NATIVE_ICON: case FEATURE_SWAP_BUFFERS: #ifdef DBUS_ENABLED case FEATURE_KEEP_SCREEN_ON: #endif case FEATURE_CLIPBOARD_PRIMARY: - case FEATURE_TEXT_TO_SPEECH: case FEATURE_WINDOW_EMBEDDING: - case FEATURE_WINDOW_DRAG: + case FEATURE_WINDOW_DRAG: { return true; - case FEATURE_SCREEN_CAPTURE: + } break; + + //case FEATURE_NATIVE_DIALOG: + //case FEATURE_NATIVE_DIALOG_INPUT: +#ifdef DBUS_ENABLED + case FEATURE_NATIVE_DIALOG_FILE: + case FEATURE_NATIVE_DIALOG_FILE_EXTRA: + case FEATURE_NATIVE_DIALOG_FILE_MIME: { + return (portal_desktop && portal_desktop->is_supported() && portal_desktop->is_file_chooser_supported()); + } break; +#endif + case FEATURE_SCREEN_CAPTURE: { return !xwayland; + } break; + +#ifdef SPEECHD_ENABLED + case FEATURE_TEXT_TO_SPEECH: { + return true; + } break; +#endif + default: { + return false; } } - - return false; } String DisplayServerX11::get_name() const { @@ -368,10 +378,13 @@ void DisplayServerX11::tts_stop() { #ifdef DBUS_ENABLED bool DisplayServerX11::is_dark_mode_supported() const { - return portal_desktop->is_supported(); + return portal_desktop && portal_desktop->is_supported() && portal_desktop->is_settings_supported(); } bool DisplayServerX11::is_dark_mode() const { + if (!is_dark_mode_supported()) { + return false; + } switch (portal_desktop->get_appearance_color_scheme()) { case 1: // Prefers dark theme.