Linux/X11: Inhibit screen saver using X11
When no supported desktop environment (e.g. KDE or Gnome) is running,
inhibit the screen saver using the X11 Screen Saver Extension.
Currently, Chromium only supports a newer FreeDesktop API for
inhibiting the screen saver which is not available on bare X11.
BUG=246060
Review URL: https://codereview.chromium.org/1616733005
Cr-Commit-Position: refs/heads/master@{#384746}
diff --git a/AUTHORS b/AUTHORS
index 0225d9b6..89caae9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -439,6 +439,8 @@
Nedeljko Babic <nedeljko.babic@imgtec.com>
Nikhil Bansal <n.bansal@samsung.com>
Nikita Ofitserov <himikof@gmail.com>
+Nils Schneider <nils@nilsschneider.net>
+Nils Schneider <nils.schneider@gmail.com>
Ningxin Hu <ningxin.hu@intel.com>
Nitish Mehrotra <nitish.m@samsung.com>
Noj Vek <nojvek@gmail.com>
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 7188165..b0b38b6 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -297,6 +297,9 @@
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
+ if (!is_chromeos) {
+ configs += [ "//build/config/linux:xscrnsaver" ]
+ }
deps += [ "//ui/gfx/x" ]
}
diff --git a/content/browser/power_save_blocker_x11.cc b/content/browser/power_save_blocker_x11.cc
index 97eefef..babc814 100644
--- a/content/browser/power_save_blocker_x11.cc
+++ b/content/browser/power_save_blocker_x11.cc
@@ -7,6 +7,7 @@
#include <X11/Xlib.h>
#include <stdint.h>
#include <X11/extensions/dpms.h>
+#include <X11/extensions/scrnsaver.h>
// Xlib #defines Status, but we can't have that for some of our headers.
#ifdef Status
#undef Status
@@ -108,12 +109,22 @@
void ApplyBlockFinished(dbus::Response* response);
void RemoveBlockFinished(dbus::Response* response);
+ // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
+ // Extension is available first. If it isn't, this is a no-op.
+ // Must be called on the UI thread.
+ static void XSSSuspendSet(bool suspend);
+
// If DPMS (the power saving system in X11) is not enabled, then we don't want
// to try to disable power saving, since on some desktop environments that may
// enable DPMS with very poor default settings (e.g. turning off the display
// after only 1 second). Must be called on the UI thread.
static bool DPMSEnabled();
+ // If no other method is available (i.e. not running under a Desktop
+ // Environment) check whether the X11 Screen Saver Extension can be used
+ // to disable the screen saver. Must be called on the UI thread.
+ static bool XSSAvailable();
+
// Returns an appropriate D-Bus API to use based on the desktop environment.
// Must be called on the UI thread, as it may call DPMSEnabled() above.
static DBusAPI SelectAPI();
@@ -180,9 +191,14 @@
// initializing on the UI thread, then just cancel it. We don't need to
// remove the block because we haven't even applied it yet.
enqueue_apply_ = false;
- } else if (ShouldBlock()) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
+ } else {
+ if (ShouldBlock()) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&Delegate::RemoveBlock, this));
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&Delegate::XSSSuspendSet, false));
}
}
@@ -190,12 +206,17 @@
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::AutoLock lock(lock_);
api_ = SelectAPI();
- if (enqueue_apply_ && ShouldBlock()) {
- // The thread we use here becomes the origin and D-Bus thread for the D-Bus
- // library, so we need to use the same thread above for RemoveBlock(). It
- // must be a thread that allows I/O operations, so we use the FILE thread.
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, this));
+
+ if (enqueue_apply_) {
+ if (ShouldBlock()) {
+ // The thread we use here becomes the origin and D-Bus thread for the
+ // D-Bus library, so we need to use the same thread above for
+ // RemoveBlock(). It must be a thread that allows I/O operations, so we
+ // use the FILE thread.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&Delegate::ApplyBlock, this));
+ }
+ XSSSuspendSet(true);
}
enqueue_apply_ = false;
}
@@ -384,6 +405,17 @@
}
// static
+void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!XSSAvailable())
+ return;
+
+ XDisplay* display = gfx::GetXDisplay();
+ XScreenSaverSuspend(display, suspend);
+}
+
+// static
bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
XDisplay* display = gfx::GetXDisplay();
@@ -397,6 +429,23 @@
}
// static
+bool PowerSaveBlockerImpl::Delegate::XSSAvailable() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ XDisplay* display = gfx::GetXDisplay();
+ int dummy;
+ int major;
+ int minor;
+
+ if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
+ return false;
+
+ if (!XScreenSaverQueryVersion(display, &major, &minor))
+ return false;
+
+ return major > 1 || (major == 1 && minor >= 1);
+}
+
+// static
DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_ptr<base::Environment> env(base::Environment::Create());
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index cbb7986..5761e08 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -2021,6 +2021,7 @@
'../build/linux/system.gyp:atk',
'../build/linux/system.gyp:gconf',
'../build/linux/system.gyp:glib',
+ '../build/linux/system.gyp:xscrnsaver',
],
'variables': {
'clang_warning_flags': [