From d3fd9d0209cda30dc4e98a4752eec5d882bb40ab Mon Sep 17 00:00:00 2001 From: dijunkun Date: Mon, 9 Nov 2026 16:18:01 +0800 Subject: [PATCH] [fix] restore Linux connections and reflect actual autostart state --- .../src/config_center/config_center.cpp | 4 +++ .../src/gui/runtime/peer_transport.cpp | 5 --- .../src/platform/linux/desktop_automation.cpp | 35 ++++++++++++++++--- .../platform/linux/gui/tray/linux_tray.cpp | 9 ++++- apps/desktop/xmake/platform.lua | 6 ++++ 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/apps/desktop/src/config_center/config_center.cpp b/apps/desktop/src/config_center/config_center.cpp index cbd7f61e..190b78dd 100644 --- a/apps/desktop/src/config_center/config_center.cpp +++ b/apps/desktop/src/config_center/config_center.cpp @@ -618,6 +618,10 @@ bool ConfigCenter::IsSelfHosted() const { return enable_self_hosted_; } bool ConfigCenter::IsEnableAutostart() const { #ifdef _WIN32 return IsServiceAutostartEnabled(); +#elif defined(__linux__) && !defined(__OHOS__) + // Uninstalling or desktop startup settings can remove the registration while + // leaving config.ini intact. Report the actual entry, not the saved intent. + return IsAutostartEnabled("CrossDesk"); #else return enable_autostart_; #endif diff --git a/apps/desktop/src/gui/runtime/peer_transport.cpp b/apps/desktop/src/gui/runtime/peer_transport.cpp index 7ff8cdbd..e3d97940 100644 --- a/apps/desktop/src/gui/runtime/peer_transport.cpp +++ b/apps/desktop/src/gui/runtime/peer_transport.cpp @@ -4,9 +4,6 @@ * Copyright (c) 2026 by DI JUNKUN, All Rights Reserved. */ -#ifndef _PEER_TRANSPORT_H_ -#define _PEER_TRANSPORT_H_ - #include "runtime/peer_transport.h" #ifdef _WIN32 @@ -100,5 +97,3 @@ int PeerUpdateConnectionSettings(MiniRtcPeerPtr* peer, bool hardware, bool av1, return MiniRtcUpdateConnectionSettings(peer, hardware, av1, turn); } } // namespace crossdesk - -#endif \ No newline at end of file diff --git a/apps/desktop/src/platform/linux/desktop_automation.cpp b/apps/desktop/src/platform/linux/desktop_automation.cpp index b7c58eab..99a460ff 100644 --- a/apps/desktop/src/platform/linux/desktop_automation.cpp +++ b/apps/desktop/src/platform/linux/desktop_automation.cpp @@ -16,6 +16,7 @@ #include #ifdef CROSSDESK_HAS_ATSPI #include +#include #endif extern char** environ; @@ -102,18 +103,44 @@ struct XConnection { } }; #ifdef CROSSDESK_HAS_ATSPI -template std::shared_ptr Own(T* object) { return {object, [](T* value) { if (value) g_object_unref(value); }}; } +// AT-SPI objects and its event loop belong to the system GLib, not MiniRTC's +// private static copy. Keep the handle for the lifetime of these objects. +struct AtspiGlib { + decltype(&g_object_unref) object_unref; + decltype(&g_free) free; + decltype(&g_main_context_pending) context_pending; + decltype(&g_main_context_iteration) context_iteration; + + AtspiGlib() { + void* library = dlopen("libatspi.so.0", RTLD_NOW | RTLD_LOCAL); + if (!library) throw std::runtime_error("ACCESSIBILITY_UNAVAILABLE"); + object_unref = reinterpret_cast(dlsym(library, "g_object_unref")); + free = reinterpret_cast(dlsym(library, "g_free")); + context_pending = reinterpret_cast(dlsym(library, "g_main_context_pending")); + context_iteration = reinterpret_cast(dlsym(library, "g_main_context_iteration")); + if (!object_unref || !free || !context_pending || !context_iteration) { + dlclose(library); + throw std::runtime_error("ACCESSIBILITY_UNAVAILABLE"); + } + } +}; +AtspiGlib& SystemGlib() { + static AtspiGlib api; + return api; +} +template std::shared_ptr Own(T* object) { return {object, [](T* value) { if (value) SystemGlib().object_unref(value); }}; } using Accessible = std::shared_ptr; std::string Text(char* value) { auto text = DesktopText(value ? value : ""); - g_free(value); + SystemGlib().free(value); return text; } Accessible Desktop() { + auto& glib = SystemGlib(); static const int initialized = atspi_init(); if (initialized > 1) throw std::runtime_error("ACCESSIBILITY_UNAVAILABLE"); atspi_set_timeout(120, 120); - for (int count = 0; count < 32 && g_main_context_pending(nullptr); ++count) g_main_context_iteration(nullptr, false); + for (int count = 0; count < 32 && glib.context_pending(nullptr); ++count) glib.context_iteration(nullptr, false); auto desktop = Own(atspi_get_desktop(0)); if (!desktop) throw std::runtime_error("ACCESSIBILITY_UNAVAILABLE"); return desktop; @@ -173,7 +200,7 @@ DesktopSnapshot Tree(Accessible root, int limit, int depth) { const auto rect = atspi_component_get_extents(component.get(), ATSPI_COORD_TYPE_SCREEN, nullptr); if (rect) { data["bounds"] = {{"x", rect->x}, {"y", rect->y}, {"width", rect->width}, {"height", rect->height}}; - g_free(rect); + SystemGlib().free(rect); } } if (!secure) { diff --git a/apps/desktop/src/platform/linux/gui/tray/linux_tray.cpp b/apps/desktop/src/platform/linux/gui/tray/linux_tray.cpp index 4c3aa8b1..7e35bbee 100644 --- a/apps/desktop/src/platform/linux/gui/tray/linux_tray.cpp +++ b/apps/desktop/src/platform/linux/gui/tray/linux_tray.cpp @@ -86,7 +86,14 @@ struct DesktopIndicatorApi { template bool LoadDesktopIndicatorSymbol(void* library, T* function, const char* symbol_name) { - *function = reinterpret_cast(dlsym(library, symbol_name)); + // MiniRTC can export a statically linked GLib/GObject. GTK's own calls then + // bind to those process-wide symbols, while a lookup through the indicator + // handle can select the system GObject's separate type registry instead. + // Match GTK's symbol resolution so menu signals and unrefs use its registry. + *function = reinterpret_cast(dlsym(RTLD_DEFAULT, symbol_name)); + if (!*function) { + *function = reinterpret_cast(dlsym(library, symbol_name)); + } return *function != nullptr; } diff --git a/apps/desktop/xmake/platform.lua b/apps/desktop/xmake/platform.lua index 0b65aa64..352e54ec 100644 --- a/apps/desktop/xmake/platform.lua +++ b/apps/desktop/xmake/platform.lua @@ -47,6 +47,12 @@ function setup_platform_settings() add_cxflags("/WX") set_runtimes("MT") elseif is_os("linux") then + -- MiniRTC carries its own static GLib/GIO. System GTK and AT-SPI must + -- keep using the system runtime, including its separate GType registry. + -- Partial ELF interposition otherwise registers GCancellable twice and + -- leaves ICE stream initialization stuck in g_once_init_enter(). + add_ldflags("-Wl,--exclude-libs,libgio-2.0.a:libgobject-2.0.a:libgthread-2.0.a:libgmodule-2.0.a:libglib-2.0.a:libffi.a", + {force = true}) add_requires("pkgconfig::atspi-2", {alias = "atspi", system = true, optional = true}) add_links("pulse-simple", "pulse") add_requires("libyuv")