1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/idle_timer.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/idle_timer.h" 1.9 + 1.10 +// We may not want to port idle_timer to Linux, but we have implemented it 1.11 +// anyway. Define this to 1 to enable the Linux idle timer and then add the 1.12 +// libs that need to be linked (Xss). 1.13 +#define ENABLE_XSS_SUPPORT 0 1.14 + 1.15 +#if defined(OS_MACOSX) 1.16 +#include <ApplicationServices/ApplicationServices.h> 1.17 +#endif 1.18 + 1.19 +#if defined(OS_LINUX) && ENABLE_XSS_SUPPORT 1.20 +// We may not want to port idle_timer to Linux, but we have implemented it 1.21 +// anyway. Remove the 0 above if we want it. 1.22 +#include <gdk/gdkx.h> 1.23 +#include <X11/extensions/scrnsaver.h> 1.24 +#include "base/lazy_instance.h" 1.25 +#include "base/thread_local.h" 1.26 +#endif 1.27 + 1.28 +#include "base/message_loop.h" 1.29 +#include "base/time.h" 1.30 + 1.31 +namespace base { 1.32 + 1.33 +#if defined(OS_WIN) 1.34 +bool OSIdleTimeSource(int32_t *milliseconds_interval_since_last_event) { 1.35 + LASTINPUTINFO lastInputInfo; 1.36 + lastInputInfo.cbSize = sizeof(lastInputInfo); 1.37 + if (GetLastInputInfo(&lastInputInfo) == 0) { 1.38 + return false; 1.39 + } 1.40 + int32_t last_input_time = lastInputInfo.dwTime; 1.41 + 1.42 + // Note: On Windows GetLastInputInfo returns a 32bit value which rolls over 1.43 + // ~49days. 1.44 + int32_t current_time = GetTickCount(); 1.45 + int32_t delta = current_time - last_input_time; 1.46 + // delta will go negative if we've been idle for 2GB of ticks. 1.47 + if (delta < 0) 1.48 + delta = -delta; 1.49 + *milliseconds_interval_since_last_event = delta; 1.50 + return true; 1.51 +} 1.52 +#elif defined(OS_MACOSX) 1.53 +bool OSIdleTimeSource(int32_t *milliseconds_interval_since_last_event) { 1.54 + *milliseconds_interval_since_last_event = 1.55 + CGEventSourceSecondsSinceLastEventType( 1.56 + kCGEventSourceStateCombinedSessionState, 1.57 + kCGAnyInputEventType) * 1000.0; 1.58 + return true; 1.59 +} 1.60 +#elif defined(OS_LINUX) && ENABLE_XSS_SUPPORT 1.61 +class IdleState { 1.62 + public: 1.63 + IdleState() { 1.64 + int event_base, error_base; 1.65 + have_idle_info_ = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, 1.66 + &error_base); 1.67 + if (have_idle_info_) 1.68 + idle_info_.Set(XScreenSaverAllocInfo()); 1.69 + } 1.70 + 1.71 + ~IdleState() { 1.72 + if (idle_info_.Get()) { 1.73 + XFree(idle_info_.Get()); 1.74 + idle_info_.~ThreadLocalPointer(); 1.75 + } 1.76 + } 1.77 + 1.78 + int32_t IdleTime() { 1.79 + if (have_idle_info_ && idle_info_.Get()) { 1.80 + XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), 1.81 + idle_info_.Get()); 1.82 + return idle_info_.Get()->idle; 1.83 + } 1.84 + return -1; 1.85 + } 1.86 + 1.87 + private: 1.88 + bool have_idle_info_; 1.89 + ThreadLocalPointer<XScreenSaverInfo> idle_info_; 1.90 + 1.91 + DISALLOW_COPY_AND_ASSIGN(IdleState); 1.92 +}; 1.93 + 1.94 +bool OSIdleTimeSource(int32_t* milliseconds_interval_since_last_event) { 1.95 + static LazyInstance<IdleState> state_instance(base::LINKER_INITIALIZED); 1.96 + IdleState* state = state_instance.Pointer(); 1.97 + int32_t idle_time = state->IdleTime(); 1.98 + if (0 < idle_time) { 1.99 + *milliseconds_interval_since_last_event = idle_time; 1.100 + return true; 1.101 + } 1.102 + return false; 1.103 +} 1.104 +#endif 1.105 + 1.106 +IdleTimer::IdleTimer(TimeDelta idle_time, bool repeat) 1.107 + : idle_interval_(idle_time), 1.108 + repeat_(repeat), 1.109 + idle_time_source_(OSIdleTimeSource) { 1.110 + DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type()) << 1.111 + "Requires a thread that processes Windows UI events"; 1.112 +} 1.113 + 1.114 +IdleTimer::~IdleTimer() { 1.115 + Stop(); 1.116 +} 1.117 + 1.118 +void IdleTimer::Start() { 1.119 + StartTimer(); 1.120 +} 1.121 + 1.122 +void IdleTimer::Stop() { 1.123 + timer_.Stop(); 1.124 +} 1.125 + 1.126 +void IdleTimer::Run() { 1.127 + // Verify we can fire the idle timer. 1.128 + if (TimeUntilIdle().InMilliseconds() <= 0) { 1.129 + OnIdle(); 1.130 + last_time_fired_ = Time::Now(); 1.131 + } 1.132 + Stop(); 1.133 + StartTimer(); // Restart the timer for next run. 1.134 +} 1.135 + 1.136 +void IdleTimer::StartTimer() { 1.137 + DCHECK(!timer_.IsRunning()); 1.138 + TimeDelta delay = TimeUntilIdle(); 1.139 + if (delay.InMilliseconds() < 0) 1.140 + delay = TimeDelta(); 1.141 + timer_.Start(delay, this, &IdleTimer::Run); 1.142 +} 1.143 + 1.144 +TimeDelta IdleTimer::CurrentIdleTime() { 1.145 + int32_t interval = 0; 1.146 + if (idle_time_source_(&interval)) { 1.147 + return TimeDelta::FromMilliseconds(interval); 1.148 + } 1.149 + NOTREACHED(); 1.150 + return TimeDelta::FromMilliseconds(0); 1.151 +} 1.152 + 1.153 +TimeDelta IdleTimer::TimeUntilIdle() { 1.154 + TimeDelta time_since_last_fire = Time::Now() - last_time_fired_; 1.155 + TimeDelta current_idle_time = CurrentIdleTime(); 1.156 + if (current_idle_time > time_since_last_fire) { 1.157 + if (repeat_) 1.158 + return idle_interval_ - time_since_last_fire; 1.159 + return idle_interval_; 1.160 + } 1.161 + return idle_interval_ - current_idle_time; 1.162 +} 1.163 + 1.164 +} // namespace base