summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewerlinux.cpp
diff options
context:
space:
mode:
authorAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-05-30 01:35:57 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-06-04 01:31:21 +0300
commit1832026b5896968bac100e67235ad242a40f2157 (patch)
treecd674130e91206bc1c9d5e031d31b63e742cf0a0 /indra/newview/llappviewerlinux.cpp
parent0797d76b7aec1e1b8fe45866cdb61147b3f531e5 (diff)
#5856 An option to prevent hibernation
Diffstat (limited to 'indra/newview/llappviewerlinux.cpp')
-rw-r--r--indra/newview/llappviewerlinux.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 89d19d180b..fe0d6f6e7d 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -58,6 +58,10 @@ namespace
void (*gOldTerminateHandler)() = NULL;
}
+// Initialize static members
+guint32 LLAppViewerLinux::sPowerInhibitCookie = 0;
+bool LLAppViewerLinux::sPowerInhibitActive = false;
+
static void exceptionTerminateHandler()
{
@@ -117,6 +121,11 @@ LLAppViewerLinux::LLAppViewerLinux()
LLAppViewerLinux::~LLAppViewerLinux()
{
+ // Clean up any power management inhibition on exit
+ if (sPowerInhibitActive)
+ {
+ uninhibitPowerManagement();
+ }
}
bool LLAppViewerLinux::init()
@@ -329,6 +338,299 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
}
#endif // LL_DBUS_ENABLED
+
+void LLAppViewerLinux::setOSHibernationMode(eHibernationMode mode)
+{
+ if (mode == LL_HIBERNATE_MODE_DEFAULT)
+ {
+ // Allow OS to sleep/hibernate - remove any inhibition
+ if (sPowerInhibitActive)
+ {
+ uninhibitPowerManagement();
+ LL_INFOS("OS") << "Permitted OS hibernation/sleep" << LL_ENDL;
+ }
+ }
+ else if (mode == LL_HIBERNATE_MODE_PREVENT)
+ {
+ // Prevent system sleep, but allow display to turn off
+ // Release any existing inhibition first to allow mode switching
+ if (sPowerInhibitActive)
+ {
+ uninhibitPowerManagement();
+ }
+
+ if (inhibitPowerManagement(false))
+ {
+ LL_INFOS("OS") << "Prevented OS hibernation/sleep, display sleep allowed" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("OS") << "Failed to prevent OS hibernation/sleep" << LL_ENDL;
+ }
+ }
+ else if (mode == LL_HIBERNATE_MODE_PREVENT_SCREEN)
+ {
+ // Prevent both system and display sleep
+ // Release any existing inhibition first to allow mode switching
+ if (sPowerInhibitActive)
+ {
+ uninhibitPowerManagement();
+ }
+
+ if (inhibitPowerManagement(true))
+ {
+ LL_INFOS("OS") << "Prevented OS hibernation/sleep and display sleep" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("OS") << "Failed to prevent OS hibernation/sleep and display sleep" << LL_ENDL;
+ }
+ }
+}
+
+// TODO: This is AI Generated!!!, needs review and testing.
+bool LLAppViewerLinux::inhibitPowerManagement(bool inhibit_display)
+{
+#if LL_DBUS_ENABLED
+ // Try to use D-Bus to inhibit power management via various desktop environment APIs
+ // This works with GNOME, KDE, XFCE, and most modern Linux desktop environments
+
+ if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
+ {
+ LL_WARNS("OS") << "Failed to load D-Bus symbols for power management" << LL_ENDL;
+ return false;
+ }
+
+ GError* error = nullptr;
+ DBusGConnection* bus = lldbus_g_bus_get(DBUS_BUS_SESSION, &error);
+
+ if (!bus)
+ {
+ LL_WARNS("OS") << "Failed to connect to D-Bus session bus: "
+ << (error ? error->message : "unknown error") << LL_ENDL;
+ if (error)
+ g_error_free(error);
+ return false;
+ }
+
+ // Try multiple power management services in order of preference
+ // 1. org.freedesktop.PowerManagement (older standard)
+ // 2. org.gnome.SessionManager (GNOME)
+ // 3. org.kde.Solid.PowerManagement (KDE)
+
+ const char* services[] = {
+ "org.freedesktop.PowerManagement",
+ "org.gnome.SessionManager",
+ "org.kde.Solid.PowerManagement"
+ };
+
+ const char* paths[] = {
+ "/org/freedesktop/PowerManagement/Inhibit",
+ "/org/gnome/SessionManager",
+ "/org/kde/Solid/PowerManagement"
+ };
+
+ const char* interfaces[] = {
+ "org.freedesktop.PowerManagement.Inhibit",
+ "org.gnome.SessionManager",
+ "org.kde.Solid.PowerManagement"
+ };
+
+ const char* methods[] = {
+ "Inhibit",
+ "Inhibit",
+ "inhibit"
+ };
+
+ bool success = false;
+
+ for (int i = 0; i < 3 && !success; ++i)
+ {
+ DBusGProxy* proxy = lldbus_g_proxy_new_for_name(
+ bus,
+ services[i],
+ paths[i],
+ interfaces[i]
+ );
+
+ if (!proxy)
+ continue;
+
+ error = nullptr;
+ guint32 cookie = 0;
+
+ if (i == 0) // freedesktop.PowerManagement
+ {
+ // Inhibit(application_name: s, reason: s) -> cookie: u
+ success = lldbus_g_proxy_call(
+ proxy,
+ methods[i],
+ &error,
+ G_TYPE_STRING, "Second Life Viewer",
+ G_TYPE_STRING, inhibit_display ?
+ "Viewer active - preventing system and display sleep" :
+ "Viewer active - preventing system sleep",
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &cookie,
+ G_TYPE_INVALID
+ );
+ }
+ else if (i == 1) // GNOME SessionManager
+ {
+ // Inhibit(app_id: s, toplevel_xid: u, reason: s, flags: u) -> cookie: u
+ // flags: 4 = suspend, 8 = idle (display), 12 = both
+ guint32 flags = inhibit_display ? 12 : 4;
+ success = lldbus_g_proxy_call(
+ proxy,
+ methods[i],
+ &error,
+ G_TYPE_STRING, "SecondLifeViewer",
+ G_TYPE_UINT, 0, // toplevel_xid (0 = none)
+ G_TYPE_STRING, inhibit_display ?
+ "Viewer active - preventing system and display sleep" :
+ "Viewer active - preventing system sleep",
+ G_TYPE_UINT, flags,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &cookie,
+ G_TYPE_INVALID
+ );
+ }
+ else if (i == 2) // KDE Solid
+ {
+ // Different method signature for KDE
+ success = lldbus_g_proxy_call(
+ proxy,
+ methods[i],
+ &error,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &cookie,
+ G_TYPE_INVALID
+ );
+ }
+
+ if (success)
+ {
+ sPowerInhibitCookie = cookie;
+ sPowerInhibitActive = true;
+ LL_INFOS("OS") << "Successfully inhibited power management using "
+ << services[i] << LL_ENDL;
+ }
+ else if (error)
+ {
+ LL_DEBUGS("OS") << "Failed to inhibit via " << services[i]
+ << ": " << error->message << LL_ENDL;
+ g_error_free(error);
+ error = nullptr;
+ }
+
+ g_object_unref(proxy);
+ }
+
+ return success;
+
+#else // !LL_DBUS_ENABLED
+ LL_WARNS("OS") << "Power management control not available - D-Bus support not enabled" << LL_ENDL;
+ return false;
+#endif
+}
+
+void LLAppViewerLinux::uninhibitPowerManagement()
+{
+#if LL_DBUS_ENABLED
+ if (!sPowerInhibitActive || sPowerInhibitCookie == 0)
+ {
+ return;
+ }
+
+ if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
+ {
+ LL_WARNS("OS") << "Failed to load D-Bus symbols for power management uninhibit" << LL_ENDL;
+ return;
+ }
+
+ GError* error = nullptr;
+ DBusGConnection* bus = lldbus_g_bus_get(DBUS_BUS_SESSION, &error);
+
+ if (!bus)
+ {
+ if (error)
+ g_error_free(error);
+ return;
+ }
+
+ // Try to uninhibit using all services that might have been used
+ const char* services[] = {
+ "org.freedesktop.PowerManagement",
+ "org.gnome.SessionManager",
+ "org.kde.Solid.PowerManagement"
+ };
+
+ const char* paths[] = {
+ "/org/freedesktop/PowerManagement/Inhibit",
+ "/org/gnome/SessionManager",
+ "/org/kde/Solid/PowerManagement"
+ };
+
+ const char* interfaces[] = {
+ "org.freedesktop.PowerManagement.Inhibit",
+ "org.gnome.SessionManager",
+ "org.kde.Solid.PowerManagement"
+ };
+
+ const char* methods[] = {
+ "UnInhibit",
+ "Uninhibit",
+ "uninhibit"
+ };
+
+ bool success = false;
+
+ for (int i = 0; i < 3; ++i)
+ {
+ DBusGProxy* proxy = lldbus_g_proxy_new_for_name(
+ bus,
+ services[i],
+ paths[i],
+ interfaces[i]
+ );
+
+ if (!proxy)
+ continue;
+
+ error = nullptr;
+
+ if (lldbus_g_proxy_call(
+ proxy,
+ methods[i],
+ &error,
+ G_TYPE_UINT, sPowerInhibitCookie,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID))
+ {
+ success = true;
+ LL_INFOS("OS") << "Successfully uninhibited power management using "
+ << services[i] << LL_ENDL;
+ }
+ else if (error)
+ {
+ LL_DEBUGS("OS") << "Failed to uninhibit via " << services[i]
+ << ": " << error->message << LL_ENDL;
+ g_error_free(error);
+ error = nullptr;
+ }
+
+ g_object_unref(proxy);
+
+ if (success)
+ break;
+ }
+
+ sPowerInhibitCookie = 0;
+ sPowerInhibitActive = false;
+
+#endif // LL_DBUS_ENABLED
+}
+
void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
{
std::string cmd =gDirUtilp->getExecutableDir();