blob: eba79585d54d76b4710fd933b7066d9936a2d006 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/idle.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <vector>
#include "base/basictypes.h"
#include "chrome/browser/idle_query_linux.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "ui/base/x/x11_util.h"
namespace {
class ScreensaverWindowFinder : public ui::EnumerateWindowsDelegate {
public:
ScreensaverWindowFinder()
: exists_(false) {}
bool exists() const { return exists_; }
protected:
virtual bool ShouldStopIterating(XID window) {
if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window))
return false;
exists_ = true;
return true;
}
private:
bool IsScreensaverWindow(XID window) const {
// It should occupy the full screen.
if (!ui::IsX11WindowFullScreen(window))
return false;
// For xscreensaver, the window should have _SCREENSAVER_VERSION property.
if (ui::PropertyExists(window, "_SCREENSAVER_VERSION"))
return true;
// For all others, like gnome-screensaver, the window's WM_CLASS property
// should contain "screensaver".
std::string value;
if (!ui::GetStringProperty(window, "WM_CLASS", &value))
return false;
return value.find("screensaver") != std::string::npos;
}
bool exists_;
DISALLOW_COPY_AND_ASSIGN(ScreensaverWindowFinder);
};
bool ScreensaverWindowExists() {
ScreensaverWindowFinder finder;
gtk_util::EnumerateTopLevelWindows(&finder);
return finder.exists();
}
}
void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) {
// Usually the screensaver is used to lock the screen, so we do not need to
// check if the workstation is locked.
gdk_error_trap_push();
bool result = ScreensaverWindowExists();
bool got_error = gdk_error_trap_pop();
if (result && !got_error) {
notify.Run(IDLE_STATE_LOCKED);
return;
}
browser::IdleQueryLinux idle_query;
unsigned int idle_time = idle_query.IdleTime();
if (idle_time >= idle_threshold)
notify.Run(IDLE_STATE_IDLE);
else
notify.Run(IDLE_STATE_ACTIVE);
}