diff options
Diffstat (limited to 'vcl/unx/generic/window/screensaverinhibitor.cxx')
-rw-r--r-- | vcl/unx/generic/window/screensaverinhibitor.cxx | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/vcl/unx/generic/window/screensaverinhibitor.cxx b/vcl/unx/generic/window/screensaverinhibitor.cxx new file mode 100644 index 000000000..4cb4e2737 --- /dev/null +++ b/vcl/unx/generic/window/screensaverinhibitor.cxx @@ -0,0 +1,370 @@ +/* -*- 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 <sal/config.h> + +#include <functional> + +#include <unx/gensys.h> +#include <unx/screensaverinhibitor.hxx> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +#if !defined(__sun) && !defined(AIX) +#include <X11/extensions/dpms.h> +#endif + +#include <config_gio.h> + +#if ENABLE_GIO +#include <gio/gio.h> + +#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 <sal/log.hxx> + +void ScreenSaverInhibitor::inhibit( bool bInhibit, const OUString& sReason, + bool bIsX11, const std::optional<unsigned int>& xid, std::optional<Display*> 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<GVariant*( GDBusProxy*, GError*& )>& fInhibit, + const std::function<GVariant*( GDBusProxy*, const guint, GError*& )>& fUnInhibit, + std::optional<guint>& 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<unsigned char*>( &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: */ |