/* -*- 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/sessioninhibitor.hxx>
#if USING_X11
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#if !defined(__sun)
#include <X11/extensions/dpms.h>
#endif
#endif
#include <config_gio.h>
#if ENABLE_GIO
#include <gio/gio.h>
#define FDOSS_DBUS_SERVICE "org.freedesktop.ScreenSaver"
#define FDOSS_DBUS_PATH "/org/freedesktop/ScreenSaver"
#define FDOSS_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"
#endif
#include <sal/log.hxx>
void SessionManagerInhibitor::inhibit(bool bInhibit, std::u16string_view sReason, ApplicationInhibitFlags eType,
unsigned int window_system_id, const char* application_id)
{
const char* appname = application_id ? application_id : SalGenericSystem::getFrameClassName();
const OString aReason = OUStringToOString( sReason, RTL_TEXTENCODING_UTF8 );
if (eType == APPLICATION_INHIBIT_IDLE)
{
inhibitFDOSS( bInhibit, appname, aReason.getStr() );
inhibitFDOPM( bInhibit, appname, aReason.getStr() );
}
inhibitGSM(bInhibit, appname, aReason.getStr(), eType, window_system_id);
}
#if USING_X11
void SessionManagerInhibitor::inhibit(bool bInhibit, std::u16string_view sReason, ApplicationInhibitFlags eType,
unsigned int window_system_id, std::optional<Display*> pDisplay,
const char* application_id)
{
inhibit(bInhibit, sReason, eType, window_system_id, application_id);
if (eType == APPLICATION_INHIBIT_IDLE && pDisplay)
{
inhibitXScreenSaver( bInhibit, *pDisplay );
inhibitXAutoLock( bInhibit, *pDisplay );
inhibitDPMS( bInhibit, *pDisplay );
}
}
#endif
#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.sessioninhibitor", "failed to connect to dbus session bus" );
if (error != nullptr) {
SAL_WARN( "vcl.sessioninhibitor", "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.sessioninhibitor", "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.sessioninhibitor", service << ".Inhibit failed");
}
}
else
{
res = fUnInhibit( proxy, *rCookie, error );
rCookie.reset();
if (res != nullptr)
{
g_variant_unref(res);
}
else
{
SAL_INFO( "vcl.sessioninhibitor", service << ".UnInhibit failed" );
}
}
if (error != nullptr)
{
SAL_INFO( "vcl.sessioninhibitor", "Error: " << error->message );
g_error_free( error );
}
g_object_unref( G_OBJECT( proxy ) );
}
#endif // ENABLE_GIO
void SessionManagerInhibitor::inhibitFDOSS( bool bInhibit, const char* appname, const char* reason )
{
#if ENABLE_GIO
dbusInhibit( bInhibit,
FDOSS_DBUS_SERVICE, FDOSS_DBUS_PATH, FDOSS_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 );
},
mnFDOSSCookie );
#else
(void) this;
(void) bInhibit;
(void) appname;
(void) reason;
#endif // ENABLE_GIO
}
void SessionManagerInhibitor::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 SessionManagerInhibitor::inhibitGSM( bool bInhibit, const char* appname, const char* reason, ApplicationInhibitFlags eType, unsigned int window_system_id )
{
#if ENABLE_GIO
dbusInhibit( bInhibit,
GSM_DBUS_SERVICE, GSM_DBUS_PATH, GSM_DBUS_INTERFACE,
[appname, reason, eType, window_system_id] ( GDBusProxy *proxy, GError*& error ) -> GVariant* {
return g_dbus_proxy_call_sync( proxy, "Inhibit",
g_variant_new("(susu)",
appname,
window_system_id,
reason,
eType
),
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) eType;
(void) window_system_id;
#endif // ENABLE_GIO
}
#if USING_X11
/**
* Disable screensavers using the XSetScreenSaver/XGetScreenSaver API.
*
* Worth noting: xscreensaver explicitly ignores this and does its own
* timeout handling.
*/
void SessionManagerInhibitor::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 SessionManagerInhibitor::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 SessionManagerInhibitor::inhibitDPMS( bool bInhibit, Display* pDisplay )
{
#if !defined(__sun)
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)
}
#endif // USING_X11
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V560 A part of conditional expression is always true: !bInhibit.
↑ V728 An excessive check can be simplified. The '(A && B) || (!A && !B)' expression is equivalent to the 'bool(A) == bool(B)' expression.