소스 검색

[FreeDesktop portal] Check for `FileChooser` and `Settings` interface availability instead of assuming it's always available.

Pāvels Nadtočajevs 7 달 전
부모
커밋
86f56efbaa

+ 56 - 0
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<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb) {
 	if (unsupported) {
 		return FAILED;

+ 7 - 0
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<String> &p_filters, const TypedArray<Dictionary> &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.

+ 5 - 2
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.

+ 26 - 13
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.