workaround segfault in compiler on macos-clang-intel
[LibreOffice.git] / vcl / unx / generic / window / sessioninhibitor.cxx
blob300df9ff80313f6f681af701f2c74c710bff0b6b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <sal/config.h>
12 #include <functional>
14 #include <unx/gensys.h>
15 #include <unx/sessioninhibitor.hxx>
17 #include <X11/Xlib.h>
18 #include <X11/Xatom.h>
20 #if !defined(__sun)
21 #include <X11/extensions/dpms.h>
22 #endif
24 #include <config_gio.h>
26 #if ENABLE_GIO
27 #include <gio/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"
45 #endif
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);
73 #if ENABLE_GIO
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 ) )
83 return;
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 );
96 return;
99 GDBusProxy *proxy = g_dbus_proxy_new_sync( session_connection,
100 G_DBUS_PROXY_FLAGS_NONE,
101 nullptr,
102 service,
103 path,
104 interface,
105 nullptr,
106 nullptr );
108 g_object_unref( G_OBJECT( session_connection ) );
110 if (proxy == nullptr) {
111 SAL_INFO( "vcl.sessioninhibitor", "could not get dbus proxy: " << service );
112 return;
115 GVariant *res = nullptr;
117 if ( bInhibit )
119 res = fInhibit( proxy, error );
121 if (res != nullptr)
123 guint nCookie;
125 g_variant_get(res, "(u)", &nCookie);
126 g_variant_unref(res);
128 rCookie = nCookie;
130 else
132 SAL_INFO( "vcl.sessioninhibitor", service << ".Inhibit failed");
135 else
137 res = fUnInhibit( proxy, *rCookie, error );
138 rCookie.reset();
140 if (res != nullptr)
142 g_variant_unref(res);
144 else
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 ) );
158 #endif // ENABLE_GIO
160 void SessionManagerInhibitor::inhibitFDOSS( bool bInhibit, const char* appname, const char* reason )
162 #if ENABLE_GIO
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 );
175 mnFDOSSCookie );
176 #else
177 (void) this;
178 (void) bInhibit;
179 (void) appname;
180 (void) reason;
181 #endif // ENABLE_GIO
184 void SessionManagerInhibitor::inhibitFDOPM( bool bInhibit, const char* appname, const char* reason )
186 #if ENABLE_GIO
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 );
199 mnFDOPMCookie );
200 #else
201 (void) this;
202 (void) bInhibit;
203 (void) appname;
204 (void) reason;
205 #endif // ENABLE_GIO
208 void SessionManagerInhibitor::inhibitGSM( bool bInhibit, const char* appname, const char* reason, ApplicationInhibitFlags eType, unsigned int window_system_id )
210 #if ENABLE_GIO
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)",
216 appname,
217 window_system_id,
218 reason,
219 eType
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 );
228 mnGSMCookie );
229 #else
230 (void) this;
231 (void) bInhibit;
232 (void) appname;
233 (void) reason;
234 (void) eType;
235 (void) window_system_id;
236 #endif // ENABLE_GIO
239 void SessionManagerInhibitor::inhibitMSM( bool bInhibit, const char* appname, const char* reason, ApplicationInhibitFlags eType, unsigned int window_system_id )
241 #if ENABLE_GIO
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)",
247 appname,
248 window_system_id,
249 reason,
250 eType
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 );
259 mnMSMCookie );
260 #else
261 (void) this;
262 (void) bInhibit;
263 (void) appname;
264 (void) reason;
265 (void) eType;
266 (void) window_system_id;
267 #endif // ENABLE_GIO
271 * Disable screensavers using the XSetScreenSaver/XGetScreenSaver API.
273 * Worth noting: xscreensaver explicitly ignores this and does its own
274 * timeout handling.
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,
295 bAllowExposures );
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,
310 "XAUTOLOCK_MESSAGE",
311 False );
313 if ( nAtom == None )
315 return;
318 int nMessage = bInhibit ? XAUTOLOCK_DISABLE : XAUTOLOCK_ENABLE;
320 XChangeProperty( pDisplay,
321 aRootWindow,
322 nAtom,
323 XA_INTEGER,
324 8, // format -- 8 bit quantity
325 PropModeReplace,
326 reinterpret_cast<unsigned char*>( &nMessage ),
327 sizeof( nMessage ) );
330 void SessionManagerInhibitor::inhibitDPMS( bool bInhibit, Display* pDisplay )
332 #if !defined(__sun)
333 int dummy;
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 )
340 return;
343 if ( bInhibit )
345 CARD16 state; // unused by us
346 DPMSInfo( pDisplay, &state, &mbDPMSWasEnabled );
348 if ( mbDPMSWasEnabled )
350 DPMSGetTimeouts( pDisplay,
351 &mnDPMSStandbyTimeout,
352 &mnDPMSSuspendTimeout,
353 &mnDPMSOffTimeout );
354 DPMSSetTimeouts( pDisplay,
357 0 );
360 else if ( !bInhibit && mbDPMSWasEnabled )
362 DPMSSetTimeouts( pDisplay,
363 mnDPMSStandbyTimeout,
364 mnDPMSSuspendTimeout,
365 mnDPMSOffTimeout );
367 #endif // !defined(__sun)
370 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */