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/sessioninhibitor.hxx>
18 #include <X11/Xatom.h>
21 #include <X11/extensions/dpms.h>
24 #include <config_gio.h>
29 #define FDOSS_DBUS_SERVICE "org.freedesktop.ScreenSaver"
30 #define FDOSS_DBUS_PATH "/org/freedesktop/ScreenSaver"
31 #define FDOSS_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 SessionManagerInhibitor::inhibit(bool bInhibit
, std::u16string_view sReason
, ApplicationInhibitFlags eType
,
50 unsigned int window_system_id
, std::optional
<Display
*> pDisplay
,
51 const char* application_id
)
53 const char* appname
= application_id
? application_id
: SalGenericSystem::getFrameClassName();
54 const OString aReason
= OUStringToOString( sReason
, RTL_TEXTENCODING_UTF8
);
56 if (eType
== APPLICATION_INHIBIT_IDLE
)
58 inhibitFDOSS( bInhibit
, appname
, aReason
.getStr() );
59 inhibitFDOPM( bInhibit
, appname
, aReason
.getStr() );
62 if (eType
== APPLICATION_INHIBIT_IDLE
&& pDisplay
)
64 inhibitXScreenSaver( bInhibit
, *pDisplay
);
65 inhibitXAutoLock( bInhibit
, *pDisplay
);
66 inhibitDPMS( bInhibit
, *pDisplay
);
69 inhibitGSM(bInhibit
, appname
, aReason
.getStr(), eType
, window_system_id
);
70 inhibitMSM(bInhibit
, appname
, aReason
.getStr(), eType
, window_system_id
);
74 static void dbusInhibit( bool bInhibit
,
75 const gchar
* service
, const gchar
* path
, const gchar
* interface
,
76 const std::function
<GVariant
*( GDBusProxy
*, GError
*& )>& fInhibit
,
77 const std::function
<GVariant
*( GDBusProxy
*, const guint
, GError
*& )>& fUnInhibit
,
78 std::optional
<guint
>& rCookie
)
80 if ( ( !bInhibit
&& !rCookie
) ||
81 ( bInhibit
&& rCookie
) )
86 GError
*error
= nullptr;
87 GDBusConnection
*session_connection
= g_bus_get_sync( G_BUS_TYPE_SESSION
, nullptr, &error
);
88 if (session_connection
== nullptr) {
89 SAL_WARN( "vcl.sessioninhibitor", "failed to connect to dbus session bus" );
91 if (error
!= nullptr) {
92 SAL_WARN( "vcl.sessioninhibitor", "Error: " << error
->message
);
93 g_error_free( error
);
99 GDBusProxy
*proxy
= g_dbus_proxy_new_sync( session_connection
,
100 G_DBUS_PROXY_FLAGS_NONE
,
108 g_object_unref( G_OBJECT( session_connection
) );
110 if (proxy
== nullptr) {
111 SAL_INFO( "vcl.sessioninhibitor", "could not get dbus proxy: " << service
);
115 GVariant
*res
= nullptr;
119 res
= fInhibit( proxy
, error
);
125 g_variant_get(res
, "(u)", &nCookie
);
126 g_variant_unref(res
);
132 SAL_INFO( "vcl.sessioninhibitor", service
<< ".Inhibit failed");
137 res
= fUnInhibit( proxy
, *rCookie
, error
);
142 g_variant_unref(res
);
146 SAL_INFO( "vcl.sessioninhibitor", service
<< ".UnInhibit failed" );
150 if (error
!= nullptr)
152 SAL_INFO( "vcl.sessioninhibitor", "Error: " << error
->message
);
153 g_error_free( error
);
156 g_object_unref( G_OBJECT( proxy
) );
160 void SessionManagerInhibitor::inhibitFDOSS( bool bInhibit
, const char* appname
, const char* reason
)
163 dbusInhibit( bInhibit
,
164 FDOSS_DBUS_SERVICE
, FDOSS_DBUS_PATH
, FDOSS_DBUS_INTERFACE
,
165 [appname
, reason
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
166 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
167 g_variant_new("(ss)", appname
, reason
),
168 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
170 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
171 return g_dbus_proxy_call_sync( proxy
, "UnInhibit",
172 g_variant_new("(u)", nCookie
),
173 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
184 void SessionManagerInhibitor::inhibitFDOPM( bool bInhibit
, const char* appname
, const char* reason
)
187 dbusInhibit( bInhibit
,
188 FDOPM_DBUS_SERVICE
, FDOPM_DBUS_PATH
, FDOPM_DBUS_INTERFACE
,
189 [appname
, reason
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
190 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
191 g_variant_new("(ss)", appname
, reason
),
192 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
194 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
195 return g_dbus_proxy_call_sync( proxy
, "UnInhibit",
196 g_variant_new("(u)", nCookie
),
197 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
208 void SessionManagerInhibitor::inhibitGSM( bool bInhibit
, const char* appname
, const char* reason
, ApplicationInhibitFlags eType
, unsigned int window_system_id
)
211 dbusInhibit( bInhibit
,
212 GSM_DBUS_SERVICE
, GSM_DBUS_PATH
, GSM_DBUS_INTERFACE
,
213 [appname
, reason
, eType
, window_system_id
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
214 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
215 g_variant_new("(susu)",
221 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
223 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
224 return g_dbus_proxy_call_sync( proxy
, "Uninhibit",
225 g_variant_new("(u)", nCookie
),
226 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
235 (void) window_system_id
;
239 void SessionManagerInhibitor::inhibitMSM( bool bInhibit
, const char* appname
, const char* reason
, ApplicationInhibitFlags eType
, unsigned int window_system_id
)
242 dbusInhibit( bInhibit
,
243 MSM_DBUS_SERVICE
, MSM_DBUS_PATH
, MSM_DBUS_INTERFACE
,
244 [appname
, reason
, eType
, window_system_id
] ( GDBusProxy
*proxy
, GError
*& error
) -> GVariant
* {
245 return g_dbus_proxy_call_sync( proxy
, "Inhibit",
246 g_variant_new("(susu)",
252 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
254 [] ( GDBusProxy
*proxy
, const guint nCookie
, GError
*& error
) -> GVariant
* {
255 return g_dbus_proxy_call_sync( proxy
, "Uninhibit",
256 g_variant_new("(u)", nCookie
),
257 G_DBUS_CALL_FLAGS_NONE
, -1, nullptr, &error
);
266 (void) window_system_id
;
271 * Disable screensavers using the XSetScreenSaver/XGetScreenSaver API.
273 * Worth noting: xscreensaver explicitly ignores this and does its own
276 void SessionManagerInhibitor::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 SessionManagerInhibitor::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 SessionManagerInhibitor::inhibitDPMS( bool bInhibit
, Display
* pDisplay
)
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)
370 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */