1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
14 #include <unx/gensys.h>
15 #include <unx/screensaverinhibitor.hxx>
18 #include <X11/Xatom.h>
20 #if !defined(__sun) && !defined(AIX)
21 #include <X11/extensions/dpms.h>
24 #include <config_gio.h>
29 #define FDO_DBUS_SERVICE "org.freedesktop.ScreenSaver"
30 #define FDO_DBUS_PATH "/org/freedesktop/ScreenSaver"
31 #define FDO_DBUS_INTERFACE "org.freedesktop.ScreenSaver"
33 #define FDOPM_DBUS_SERVICE "org.freedesktop.PowerManagement.Inhibit"
34 #define FDOPM_DBUS_PATH "/org/freedesktop/PowerManagement/Inhibit"
35 #define FDOPM_DBUS_INTERFACE "org.freedesktop.PowerManagement.Inhibit"
37 #define GSM_DBUS_SERVICE "org.gnome.SessionManager"
38 #define GSM_DBUS_PATH "/org/gnome/SessionManager"
39 #define GSM_DBUS_INTERFACE "org.gnome.SessionManager"
41 // Mate <= 1.10 uses org.mate.SessionManager, > 1.10 will use org.gnome.SessionManager
42 #define MSM_DBUS_SERVICE "org.mate.SessionManager"
43 #define MSM_DBUS_PATH "/org/mate/SessionManager"
44 #define MSM_DBUS_INTERFACE "org.mate.SessionManager"
47 #include <sal/log.hxx>
49 void ScreenSaverInhibitor::inhibit( bool bInhibit
, const OUString
& sReason
,
50 bool bIsX11
, const std::optional
<unsigned int>& xid
, std::optional
<Display
*> pDisplay
)
52 const char* appname
= SalGenericSystem::getFrameClassName();
53 const OString aReason
= OUStringToOString( sReason
, RTL_TEXTENCODING_UTF8
);
55 inhibitFDO( bInhibit
, appname
, aReason
.getStr() );
56 inhibitFDOPM( bInhibit
, appname
, aReason
.getStr() );
63 inhibitXScreenSaver( bInhibit
, *pDisplay
);
64 inhibitXAutoLock( bInhibit
, *pDisplay
);
65 inhibitDPMS( bInhibit
, *pDisplay
);
70 inhibitGSM( bInhibit
, appname
, aReason
.getStr(), *xid
);
71 inhibitMSM( bInhibit
, appname
, aReason
.getStr(), *xid
);
76 static void dbusInhibit( bool bInhibit
,
77 const gchar
* service
, const gchar
* path
, const gchar
* interface
,
78 const std::function
<GVariant
*( GDBusProxy
*, GError
*& )>& fInhibit
,
79 const std::function
<GVariant
*( GDBusProxy
*, const guint
, GError
*& )>& fUnInhibit
,
80 std::optional
<guint
>& rCookie
)
82 if ( ( !bInhibit
&& !rCookie
) ||
83 ( bInhibit
&& rCookie
) )
88 GError
*error
= nullptr;
89 GDBusConnection
*session_connection
= g_bus_get_sync( G_BUS_TYPE_SESSION
, nullptr, &error
);
90 if (session_connection
== nullptr) {
91 SAL_WARN( "vcl.screensaverinhibitor", "failed to connect to dbus session bus" );
93 if (error
!= nullptr) {
94 SAL_WARN( "vcl.screensaverinhibitor", "Error: " << error
->message
);
95 g_error_free( error
);
101 GDBusProxy
*proxy
= g_dbus_proxy_new_sync( session_connection
,
102 G_DBUS_PROXY_FLAGS_NONE
,
110 g_object_unref( G_OBJECT( session_connection
) );
112 if (proxy
== nullptr) {
113 SAL_INFO( "vcl.screensaverinhibitor", "could not get dbus proxy: " << service
);
117 GVariant
*res
= nullptr;
121 res
= fInhibit( proxy
, error
);
127 g_variant_get(res
, "(u)", &nCookie
);
128 g_variant_unref(res
);
134 SAL_INFO( "vcl.screensaverinhibitor", service
<< ".Inhibit failed");
139 res
= fUnInhibit( proxy
, *rCookie
, error
);
144 g_variant_unref(res
);
148 SAL_INFO( "vcl.screensaverinhibitor", service
<< ".UnInhibit failed" );
152 if (error
!= nullptr)
154 SAL_INFO( "vcl.screensaverinhibitor", "Error: " << error
->message
);
155 g_error_free( error
);
158 g_object_unref( G_OBJECT( proxy
) );
162 void ScreenSaverInhibitor::inhibitFDO( bool bInhibit
, const char* appname
, const char* reason
)
165 dbusInhibit( bInhibit
,
166 FDO_DBUS_SERVICE
, FDO_DBUS_PATH
, FDO_DBUS_INTERFACE
,
167 [appname
, reason
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
168 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
169 g_variant_new("(ss)", appname
, reason
),
170 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
172 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
173 return g_dbus_proxy_call_sync( proxy
, "UnInhibit",
174 g_variant_new("(u)", nCookie
),
175 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
186 void ScreenSaverInhibitor::inhibitFDOPM( bool bInhibit
, const char* appname
, const char* reason
)
189 dbusInhibit( bInhibit
,
190 FDOPM_DBUS_SERVICE
, FDOPM_DBUS_PATH
, FDOPM_DBUS_INTERFACE
,
191 [appname
, reason
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
192 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
193 g_variant_new("(ss)", appname
, reason
),
194 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
196 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
197 return g_dbus_proxy_call_sync( proxy
, "UnInhibit",
198 g_variant_new("(u)", nCookie
),
199 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
210 void ScreenSaverInhibitor::inhibitGSM( bool bInhibit
, const char* appname
, const char* reason
, const unsigned int xid
)
213 dbusInhibit( bInhibit
,
214 GSM_DBUS_SERVICE
, GSM_DBUS_PATH
, GSM_DBUS_INTERFACE
,
215 [appname
, reason
, xid
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
216 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
217 g_variant_new("(susu)",
221 8 //Inhibit the session being marked as idle
223 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
225 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
226 return g_dbus_proxy_call_sync( proxy
, "Uninhibit",
227 g_variant_new("(u)", nCookie
),
228 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
240 void ScreenSaverInhibitor::inhibitMSM( bool bInhibit
, const char* appname
, const char* reason
, const unsigned int xid
)
243 dbusInhibit( bInhibit
,
244 MSM_DBUS_SERVICE
, MSM_DBUS_PATH
, MSM_DBUS_INTERFACE
,
245 [appname
, reason
, xid
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
246 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
247 g_variant_new("(susu)",
251 8 //Inhibit the session being marked as idle
253 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
255 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
256 return g_dbus_proxy_call_sync( proxy
, "Uninhibit",
257 g_variant_new("(u)", nCookie
),
258 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
271 * Disable screensavers using the XSetScreenSaver/XGetScreenSaver API.
273 * Worth noting: xscreensaver explicitly ignores this and does its own
276 void ScreenSaverInhibitor::inhibitXScreenSaver( bool bInhibit
, Display
* pDisplay
)
278 int nTimeout
, nInterval
, bPreferBlanking
, bAllowExposures
;
279 XGetScreenSaver( pDisplay
, &nTimeout
, &nInterval
,
280 &bPreferBlanking
, &bAllowExposures
);
282 // To disable/reenable we simply fiddle the timeout, whilst
283 // retaining all other properties.
284 if ( bInhibit
&& nTimeout
)
286 mnXScreenSaverTimeout
= nTimeout
;
287 XResetScreenSaver( pDisplay
);
288 XSetScreenSaver( pDisplay
, 0, nInterval
,
289 bPreferBlanking
, bAllowExposures
);
291 else if ( !bInhibit
&& mnXScreenSaverTimeout
)
293 XSetScreenSaver( pDisplay
, *mnXScreenSaverTimeout
,
294 nInterval
, bPreferBlanking
,
296 mnXScreenSaverTimeout
.reset();
301 /* definitions from xautolock.c (pl15) */
302 #define XAUTOLOCK_DISABLE 1
303 #define XAUTOLOCK_ENABLE 2
305 void ScreenSaverInhibitor::inhibitXAutoLock( bool bInhibit
, Display
* pDisplay
)
307 ::Window aRootWindow
= RootWindowOfScreen( ScreenOfDisplay( pDisplay
, 0 ) );
309 Atom nAtom
= XInternAtom( pDisplay
,
318 int nMessage
= bInhibit
? XAUTOLOCK_DISABLE
: XAUTOLOCK_ENABLE
;
320 XChangeProperty( pDisplay
,
324 8, // format -- 8 bit quantity
326 reinterpret_cast<unsigned char*>( &nMessage
),
327 sizeof( nMessage
) );
330 void ScreenSaverInhibitor::inhibitDPMS( bool bInhibit
, Display
* pDisplay
)
332 #if !defined(__sun) && !defined(AIX)
334 // This won't change while X11 is running, hence
335 // we can evaluate only once and store as static
336 static bool bDPMSExtensionAvailable
= ( DPMSQueryExtension( pDisplay
, &dummy
, &dummy
) != 0 );
338 if ( !bDPMSExtensionAvailable
)
345 CARD16 state
; // unused by us
346 DPMSInfo( pDisplay
, &state
, &mbDPMSWasEnabled
);
348 if ( mbDPMSWasEnabled
)
350 DPMSGetTimeouts( pDisplay
,
351 &mnDPMSStandbyTimeout
,
352 &mnDPMSSuspendTimeout
,
354 DPMSSetTimeouts( pDisplay
,
360 else if ( !bInhibit
&& mbDPMSWasEnabled
)
362 DPMSSetTimeouts( pDisplay
,
363 mnDPMSStandbyTimeout
,
364 mnDPMSSuspendTimeout
,
367 #endif // !defined(__sun) && !defined(AIX)
370 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */