/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #if !defined(__sun) && !defined(AIX) #include #endif #include #if ENABLE_GIO #include #define FDO_DBUS_SERVICE "org.freedesktop.ScreenSaver" #define FDO_DBUS_PATH "/org/freedesktop/ScreenSaver" #define FDO_DBUS_INTERFACE "org.freedesktop.ScreenSaver" #define FDOPM_DBUS_SERVICE "org.freedesktop.PowerManagement.Inhibit" #define FDOPM_DBUS_PATH "/org/freedesktop/PowerManagement/Inhibit" #define FDOPM_DBUS_INTERFACE "org.freedesktop.PowerManagement.Inhibit" #define GSM_DBUS_SERVICE "org.gnome.SessionManager" #define GSM_DBUS_PATH "/org/gnome/SessionManager" #define GSM_DBUS_INTERFACE "org.gnome.SessionManager" // Mate <= 1.10 uses org.mate.SessionManager, > 1.10 will use org.gnome.SessionManager #define MSM_DBUS_SERVICE "org.mate.SessionManager" #define MSM_DBUS_PATH "/org/mate/SessionManager" #define MSM_DBUS_INTERFACE "org.mate.SessionManager" #endif #include void ScreenSaverInhibitor::inhibit( bool bInhibit, const OUString& sReason, bool bIsX11, const std::optional& xid, std::optional pDisplay ) { const char* appname = SalGenericSystem::getFrameClassName(); const OString aReason = OUStringToOString( sReason, RTL_TEXTENCODING_UTF8 ); inhibitFDO( bInhibit, appname, aReason.getStr() ); inhibitFDOPM( bInhibit, appname, aReason.getStr() ); if ( bIsX11 ) { if (pDisplay) { inhibitXScreenSaver( bInhibit, *pDisplay ); inhibitXAutoLock( bInhibit, *pDisplay ); inhibitDPMS( bInhibit, *pDisplay ); } if (xid) { inhibitGSM( bInhibit, appname, aReason.getStr(), *xid ); inhibitMSM( bInhibit, appname, aReason.getStr(), *xid ); } } } #if ENABLE_GIO static void dbusInhibit( bool bInhibit, const gchar* service, const gchar* path, const gchar* interface, const std::function& fInhibit, const std::function& fUnInhibit, std::optional& rCookie ) { if ( ( !bInhibit && !rCookie ) || ( bInhibit && rCookie ) ) { return; } GError *error = nullptr; GDBusConnection *session_connection = g_bus_get_sync( G_BUS_TYPE_SESSION, nullptr, &error ); if (session_connection == nullptr) { SAL_WARN( "vcl.screensaverinhibitor", "failed to connect to dbus session bus" ); if (error != nullptr) { SAL_WARN( "vcl.screensaverinhibitor", "Error: " << error->message ); g_error_free( error ); } return; } GDBusProxy *proxy = g_dbus_proxy_new_sync( session_connection, G_DBUS_PROXY_FLAGS_NONE, nullptr, service, path, interface, nullptr, nullptr ); g_object_unref( G_OBJECT( session_connection ) ); if (proxy == nullptr) { SAL_INFO( "vcl.screensaverinhibitor", "could not get dbus proxy: " << service ); return; } GVariant *res = nullptr; if ( bInhibit ) { res = fInhibit( proxy, error ); if (res != nullptr) { guint nCookie; g_variant_get(res, "(u)", &nCookie); g_variant_unref(res); rCookie = nCookie; } else { SAL_INFO( "vcl.screensaverinhibitor", service << ".Inhibit failed"); } } else { res = fUnInhibit( proxy, *rCookie, error ); rCookie.reset(); if (res != nullptr) { g_variant_unref(res); } else { SAL_INFO( "vcl.screensaverinhibitor", service << ".UnInhibit failed" ); } } if (error != nullptr) { SAL_INFO( "vcl.screensaverinhibitor", "Error: " << error->message ); g_error_free( error ); } g_object_unref( G_OBJECT( proxy ) ); } #endif // ENABLE_GIO void ScreenSaverInhibitor::inhibitFDO( bool bInhibit, const char* appname, const char* reason ) { #if ENABLE_GIO dbusInhibit( bInhibit, FDO_DBUS_SERVICE, FDO_DBUS_PATH, FDO_DBUS_INTERFACE, [appname, reason] ( GDBusProxy *proxy, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Inhibit", g_variant_new("(ss)", appname, reason), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, [] ( GDBusProxy *proxy, const guint nCookie, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "UnInhibit", g_variant_new("(u)", nCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, mnFDOCookie ); #else (void) this; (void) bInhibit; (void) appname; (void) reason; #endif // ENABLE_GIO } void ScreenSaverInhibitor::inhibitFDOPM( bool bInhibit, const char* appname, const char* reason ) { #if ENABLE_GIO dbusInhibit( bInhibit, FDOPM_DBUS_SERVICE, FDOPM_DBUS_PATH, FDOPM_DBUS_INTERFACE, [appname, reason] ( GDBusProxy *proxy, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Inhibit", g_variant_new("(ss)", appname, reason), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, [] ( GDBusProxy *proxy, const guint nCookie, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "UnInhibit", g_variant_new("(u)", nCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, mnFDOPMCookie ); #else (void) this; (void) bInhibit; (void) appname; (void) reason; #endif // ENABLE_GIO } void ScreenSaverInhibitor::inhibitGSM( bool bInhibit, const char* appname, const char* reason, const unsigned int xid ) { #if ENABLE_GIO dbusInhibit( bInhibit, GSM_DBUS_SERVICE, GSM_DBUS_PATH, GSM_DBUS_INTERFACE, [appname, reason, xid] ( GDBusProxy *proxy, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Inhibit", g_variant_new("(susu)", appname, xid, reason, 8 //Inhibit the session being marked as idle ), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, [] ( GDBusProxy *proxy, const guint nCookie, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Uninhibit", g_variant_new("(u)", nCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, mnGSMCookie ); #else (void) this; (void) bInhibit; (void) appname; (void) reason; (void) xid; #endif // ENABLE_GIO } void ScreenSaverInhibitor::inhibitMSM( bool bInhibit, const char* appname, const char* reason, const unsigned int xid ) { #if ENABLE_GIO dbusInhibit( bInhibit, MSM_DBUS_SERVICE, MSM_DBUS_PATH, MSM_DBUS_INTERFACE, [appname, reason, xid] ( GDBusProxy *proxy, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Inhibit", g_variant_new("(susu)", appname, xid, reason, 8 //Inhibit the session being marked as idle ), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, [] ( GDBusProxy *proxy, const guint nCookie, GError*& error ) -> GVariant* { return g_dbus_proxy_call_sync( proxy, "Uninhibit", g_variant_new("(u)", nCookie), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error ); }, mnMSMCookie ); #else (void) this; (void) bInhibit; (void) appname; (void) reason; (void) xid; #endif // ENABLE_GIO } /** * Disable screensavers using the XSetScreenSaver/XGetScreenSaver API. * * Worth noting: xscreensaver explicitly ignores this and does its own * timeout handling. */ void ScreenSaverInhibitor::inhibitXScreenSaver( bool bInhibit, Display* pDisplay ) { int nTimeout, nInterval, bPreferBlanking, bAllowExposures; XGetScreenSaver( pDisplay, &nTimeout, &nInterval, &bPreferBlanking, &bAllowExposures ); // To disable/reenable we simply fiddle the timeout, whilst // retaining all other properties. if ( bInhibit && nTimeout) { mnXScreenSaverTimeout = nTimeout; XResetScreenSaver( pDisplay ); XSetScreenSaver( pDisplay, 0, nInterval, bPreferBlanking, bAllowExposures ); } else if ( !bInhibit && mnXScreenSaverTimeout ) { XSetScreenSaver( pDisplay, *mnXScreenSaverTimeout, nInterval, bPreferBlanking, bAllowExposures ); mnXScreenSaverTimeout.reset(); } } /* definitions from xautolock.c (pl15) */ #define XAUTOLOCK_DISABLE 1 #define XAUTOLOCK_ENABLE 2 void ScreenSaverInhibitor::inhibitXAutoLock( bool bInhibit, Display* pDisplay ) { ::Window aRootWindow = RootWindowOfScreen( ScreenOfDisplay( pDisplay, 0 ) ); Atom nAtom = XInternAtom( pDisplay, "XAUTOLOCK_MESSAGE", False ); if ( nAtom == None ) { return; } int nMessage = bInhibit ? XAUTOLOCK_DISABLE : XAUTOLOCK_ENABLE; XChangeProperty( pDisplay, aRootWindow, nAtom, XA_INTEGER, 8, // format -- 8 bit quantity PropModeReplace, reinterpret_cast( &nMessage ), sizeof( nMessage ) ); } void ScreenSaverInhibitor::inhibitDPMS( bool bInhibit, Display* pDisplay ) { #if !defined(__sun) && !defined(AIX) int dummy; // This won't change while X11 is running, hence // we can evaluate only once and store as static static bool bDPMSExtensionAvailable = ( DPMSQueryExtension( pDisplay, &dummy, &dummy) != 0 ); if ( !bDPMSExtensionAvailable ) { return; } if ( bInhibit ) { CARD16 state; // unused by us DPMSInfo( pDisplay, &state, &mbDPMSWasEnabled ); if ( mbDPMSWasEnabled ) { DPMSGetTimeouts( pDisplay, &mnDPMSStandbyTimeout, &mnDPMSSuspendTimeout, &mnDPMSOffTimeout ); DPMSSetTimeouts( pDisplay, 0, 0, 0 ); } } else if ( !bInhibit && mbDPMSWasEnabled ) { DPMSSetTimeouts( pDisplay, mnDPMSStandbyTimeout, mnDPMSSuspendTimeout, mnDPMSOffTimeout ); } #endif // !defined(__sun) && !defined(AIX) } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */