Add "Keep screen on" feature to DisplayServerX11

This commit is contained in:
Niklas Higi 2020-04-02 23:46:34 +02:00
parent 953de68cfc
commit 0c83a23ab5
No known key found for this signature in database
GPG key ID: C0B475782514B03F
7 changed files with 230 additions and 3 deletions

View file

@ -26,7 +26,7 @@ jobs:
- name: Configure dependencies - name: Configure dependencies
run: | run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm
# Upload cache on completion and check it out now # Upload cache on completion and check it out now
- name: Load .scons_cache directory - name: Load .scons_cache directory
@ -111,7 +111,7 @@ jobs:
- name: Configure dependencies - name: Configure dependencies
run: | run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm \ libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm \
xvfb wget unzip xvfb wget unzip
# Upload cache on completion and check it out now # Upload cache on completion and check it out now
@ -204,7 +204,7 @@ jobs:
- name: Configure dependencies - name: Configure dependencies
run: | run: |
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \ sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev yasm libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm
# Upload cache on completion and check it out now # Upload cache on completion and check it out now
- name: Load .scons_cache directory - name: Load .scons_cache directory

View file

@ -9,6 +9,7 @@ common_linuxbsd = [
"crash_handler_linuxbsd.cpp", "crash_handler_linuxbsd.cpp",
"os_linuxbsd.cpp", "os_linuxbsd.cpp",
"joypad_linux.cpp", "joypad_linux.cpp",
"freedesktop_screensaver.cpp",
] ]
if "x11" in env and env["x11"]: if "x11" in env and env["x11"]:

View file

@ -72,6 +72,7 @@ def get_opts():
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False), BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False), BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
BoolVariable("pulseaudio", "Detect and use PulseAudio", True), BoolVariable("pulseaudio", "Detect and use PulseAudio", True),
BoolVariable("dbus", "Detect and use D-Bus to handle screensaver", True),
BoolVariable("udev", "Use udev for gamepad connection callbacks", True), BoolVariable("udev", "Use udev for gamepad connection callbacks", True),
BoolVariable("x11", "Enable X11 display", True), BoolVariable("x11", "Enable X11 display", True),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
@ -347,6 +348,14 @@ def configure(env):
else: else:
print("PulseAudio development libraries not found, disabling driver") print("PulseAudio development libraries not found, disabling driver")
if env["dbus"]:
if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
print("Enabling D-Bus")
env.Append(CPPDEFINES=["DBUS_ENABLED"])
env.ParseConfig("pkg-config --cflags --libs dbus-1")
else:
print("D-Bus development libraries not found, disabling dependent features")
if platform.system() == "Linux": if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"]) env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
if env["udev"]: if env["udev"]:

View file

@ -121,6 +121,9 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
case FEATURE_ICON: case FEATURE_ICON:
case FEATURE_NATIVE_ICON: case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS: case FEATURE_SWAP_BUFFERS:
#ifdef DBUS_ENABLED
case FEATURE_KEEP_SCREEN_ON:
#endif
return true; return true;
default: { default: {
} }
@ -822,6 +825,26 @@ bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {
return DisplayServer::screen_is_touchscreen(p_screen); return DisplayServer::screen_is_touchscreen(p_screen);
} }
#ifdef DBUS_ENABLED
void DisplayServerX11::screen_set_keep_on(bool p_enable) {
if (screen_is_kept_on() == p_enable) {
return;
}
if (p_enable) {
screensaver->inhibit();
} else {
screensaver->uninhibit();
}
keep_screen_on = p_enable;
}
bool DisplayServerX11::screen_is_kept_on() const {
return keep_screen_on;
}
#endif
Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const { Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
@ -4270,6 +4293,11 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
_update_real_mouse_position(windows[MAIN_WINDOW_ID]); _update_real_mouse_position(windows[MAIN_WINDOW_ID]);
#ifdef DBUS_ENABLED
screensaver = memnew(FreeDesktopScreenSaver);
screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
#endif
r_error = OK; r_error = OK;
} }
@ -4334,6 +4362,10 @@ DisplayServerX11::~DisplayServerX11() {
if (xmbstring) { if (xmbstring) {
memfree(xmbstring); memfree(xmbstring);
} }
#ifdef DBUS_ENABLED
memdelete(screensaver);
#endif
} }
void DisplayServerX11::register_x11_driver() { void DisplayServerX11::register_x11_driver() {

View file

@ -55,6 +55,10 @@
#include "platform/linuxbsd/vulkan_context_x11.h" #include "platform/linuxbsd/vulkan_context_x11.h"
#endif #endif
#if defined(DBUS_ENABLED)
#include "freedesktop_screensaver.h"
#endif
#include <X11/Xcursor/Xcursor.h> #include <X11/Xcursor/Xcursor.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/XInput2.h> #include <X11/extensions/XInput2.h>
@ -103,6 +107,11 @@ class DisplayServerX11 : public DisplayServer {
RenderingDeviceVulkan *rendering_device_vulkan; RenderingDeviceVulkan *rendering_device_vulkan;
#endif #endif
#if defined(DBUS_ENABLED)
FreeDesktopScreenSaver *screensaver;
bool keep_screen_on = false;
#endif
struct WindowData { struct WindowData {
Window x11_window; Window x11_window;
::XIC xic; ::XIC xic;
@ -291,6 +300,11 @@ public:
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const; virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
#if defined(DBUS_ENABLED)
virtual void screen_set_keep_on(bool p_enable);
virtual bool screen_is_kept_on() const;
#endif
virtual Vector<DisplayServer::WindowID> get_window_list() const; virtual Vector<DisplayServer::WindowID> get_window_list() const;
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());

View file

@ -0,0 +1,124 @@
/*************************************************************************/
/* freedesktop_screensaver.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "freedesktop_screensaver.h"
#ifdef DBUS_ENABLED
#include "core/config/project_settings.h"
#include <dbus/dbus.h>
#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
#define BUS_INTERFACE "org.freedesktop.ScreenSaver"
void FreeDesktopScreenSaver::inhibit() {
if (unsupported) {
return;
}
DBusError error;
dbus_error_init(&error);
DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
unsupported = true;
return;
}
String app_name_string = ProjectSettings::get_singleton()->get("application/config/name");
const char *app_name = app_name_string.is_empty() ? "Godot Engine" : app_name_string.utf8().get_data();
const char *reason = "Running Godot Engine project";
DBusMessage *message = dbus_message_new_method_call(
BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
"Inhibit");
dbus_message_append_args(
message,
DBUS_TYPE_STRING, &app_name,
DBUS_TYPE_STRING, &reason,
DBUS_TYPE_INVALID);
DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
dbus_message_unref(message);
if (dbus_error_is_set(&error)) {
dbus_connection_unref(bus);
unsupported = false;
return;
}
DBusMessageIter reply_iter;
dbus_message_iter_init(reply, &reply_iter);
dbus_message_iter_get_basic(&reply_iter, &cookie);
print_verbose("FreeDesktopScreenSaver: Acquired screensaver inhibition cookie: " + uitos(cookie));
dbus_message_unref(reply);
dbus_connection_unref(bus);
}
void FreeDesktopScreenSaver::uninhibit() {
if (unsupported) {
return;
}
DBusError error;
dbus_error_init(&error);
DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
unsupported = true;
return;
}
DBusMessage *message = dbus_message_new_method_call(
BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE,
"UnInhibit");
dbus_message_append_args(
message,
DBUS_TYPE_UINT32, &cookie,
DBUS_TYPE_INVALID);
DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
if (dbus_error_is_set(&error)) {
dbus_connection_unref(bus);
unsupported = true;
return;
}
print_verbose("FreeDesktopScreenSaver: Released screensaver inhibition cookie: " + uitos(cookie));
dbus_message_unref(message);
dbus_message_unref(reply);
dbus_connection_unref(bus);
}
#endif // DBUS_ENABLED

View file

@ -0,0 +1,47 @@
/*************************************************************************/
/* freedesktop_screensaver.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef DBUS_ENABLED
#include <dbus/dbus.h>
#include <stdint.h>
class FreeDesktopScreenSaver {
private:
uint32_t cookie = 0;
bool unsupported = false;
public:
FreeDesktopScreenSaver() {}
void inhibit();
void uninhibit();
};
#endif // DBUS_ENABLED