1/**************************************************************************/
2/* freedesktop_screensaver.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "freedesktop_screensaver.h"
32
33#ifdef DBUS_ENABLED
34
35#include "core/config/project_settings.h"
36
37#ifdef SOWRAP_ENABLED
38#include "dbus-so_wrap.h"
39#else
40#include <dbus/dbus.h>
41#endif
42
43#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
44#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
45#define BUS_INTERFACE "org.freedesktop.ScreenSaver"
46
47void FreeDesktopScreenSaver::inhibit() {
48 if (unsupported) {
49 return;
50 }
51
52 DBusError error;
53 dbus_error_init(&error);
54
55 DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
56 if (dbus_error_is_set(&error)) {
57 dbus_error_free(&error);
58 unsupported = true;
59 return;
60 }
61
62 String app_name_string = GLOBAL_GET("application/config/name");
63 CharString app_name_utf8 = app_name_string.utf8();
64 const char *app_name = app_name_string.is_empty() ? "Godot Engine" : app_name_utf8.get_data();
65
66 const char *reason = "Running Godot Engine project";
67
68 DBusMessage *message = dbus_message_new_method_call(
69 BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
70 "Inhibit");
71 dbus_message_append_args(
72 message,
73 DBUS_TYPE_STRING, &app_name,
74 DBUS_TYPE_STRING, &reason,
75 DBUS_TYPE_INVALID);
76
77 DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
78 dbus_message_unref(message);
79 if (dbus_error_is_set(&error)) {
80 dbus_error_free(&error);
81 dbus_connection_unref(bus);
82 unsupported = false;
83 return;
84 }
85
86 DBusMessageIter reply_iter;
87 dbus_message_iter_init(reply, &reply_iter);
88 dbus_message_iter_get_basic(&reply_iter, &cookie);
89 print_verbose("FreeDesktopScreenSaver: Acquired screensaver inhibition cookie: " + uitos(cookie));
90
91 dbus_message_unref(reply);
92 dbus_connection_unref(bus);
93}
94
95void FreeDesktopScreenSaver::uninhibit() {
96 if (unsupported) {
97 return;
98 }
99
100 DBusError error;
101 dbus_error_init(&error);
102
103 DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
104 if (dbus_error_is_set(&error)) {
105 dbus_error_free(&error);
106 unsupported = true;
107 return;
108 }
109
110 DBusMessage *message = dbus_message_new_method_call(
111 BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
112 "UnInhibit");
113 dbus_message_append_args(
114 message,
115 DBUS_TYPE_UINT32, &cookie,
116 DBUS_TYPE_INVALID);
117
118 DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
119 if (dbus_error_is_set(&error)) {
120 dbus_error_free(&error);
121 dbus_connection_unref(bus);
122 unsupported = true;
123 return;
124 }
125
126 print_verbose("FreeDesktopScreenSaver: Released screensaver inhibition cookie: " + uitos(cookie));
127
128 dbus_message_unref(message);
129 dbus_message_unref(reply);
130 dbus_connection_unref(bus);
131}
132
133FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
134#ifdef SOWRAP_ENABLED
135#ifdef DEBUG_ENABLED
136 int dylibloader_verbose = 1;
137#else
138 int dylibloader_verbose = 0;
139#endif
140 unsupported = (initialize_dbus(dylibloader_verbose) != 0);
141#else
142 unsupported = false;
143#endif
144
145 if (unsupported) {
146 return;
147 }
148
149 bool ver_ok = false;
150 int version_major = 0;
151 int version_minor = 0;
152 int version_rev = 0;
153 dbus_get_version(&version_major, &version_minor, &version_rev);
154 ver_ok = (version_major == 1 && version_minor >= 10) || (version_major > 1); // 1.10.0
155 print_verbose(vformat("ScreenSaver: DBus %d.%d.%d detected.", version_major, version_minor, version_rev));
156 if (!ver_ok) {
157 print_verbose("ScreenSaver:: Unsupported DBus library version!");
158 unsupported = true;
159 }
160}
161
162#endif // DBUS_ENABLED
163