// Copyright 2014 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 "ui/base/user_activity/user_activity_detector.h" #include "base/format_macros.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "ui/base/user_activity/user_activity_observer.h" #include "ui/events/event_utils.h" #include "ui/events/platform/platform_event_source.h" namespace ui { namespace { UserActivityDetector* g_instance = nullptr; // Returns a string describing |event|. std::string GetEventDebugString(const ui::Event* event) { std::string details = base::StringPrintf( "type=%d name=%s flags=%d time=%" PRId64, event->type(), event->name().c_str(), event->flags(), event->time_stamp().InMilliseconds()); if (event->IsKeyEvent()) { details += base::StringPrintf(" key_code=%d", static_cast(event)->key_code()); } else if (event->IsMouseEvent() || event->IsTouchEvent() || event->IsGestureEvent()) { details += base::StringPrintf(" location=%s", static_cast( event)->location().ToString().c_str()); } return details; } } // namespace const int UserActivityDetector::kNotifyIntervalMs = 200; // Too low and mouse events generated at the tail end of reconfiguration // will be reported as user activity and turn the screen back on; too high // and we'll ignore legitimate activity. const int UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs = 1000; UserActivityDetector::UserActivityDetector() { CHECK(!g_instance); g_instance = this; ui::PlatformEventSource* platform_event_source = ui::PlatformEventSource::GetInstance(); // TODO(sad): Need a PES for mus. if (platform_event_source) platform_event_source->AddPlatformEventObserver(this); } UserActivityDetector::~UserActivityDetector() { ui::PlatformEventSource* platform_event_source = ui::PlatformEventSource::GetInstance(); if (platform_event_source) platform_event_source->RemovePlatformEventObserver(this); g_instance = nullptr; } // static UserActivityDetector* UserActivityDetector::Get() { return g_instance; } bool UserActivityDetector::HasObserver( const UserActivityObserver* observer) const { return observers_.HasObserver(observer); } void UserActivityDetector::AddObserver(UserActivityObserver* observer) { observers_.AddObserver(observer); } void UserActivityDetector::RemoveObserver(UserActivityObserver* observer) { observers_.RemoveObserver(observer); } void UserActivityDetector::OnDisplayPowerChanging() { honor_mouse_events_time_ = GetCurrentTime() + base::TimeDelta::FromMilliseconds(kDisplayPowerChangeIgnoreMouseMs); } void UserActivityDetector::DidProcessEvent( const PlatformEvent& platform_event) { scoped_ptr event(ui::EventFromNative(platform_event)); ProcessReceivedEvent(event.get()); } base::TimeTicks UserActivityDetector::GetCurrentTime() const { return !now_for_test_.is_null() ? now_for_test_ : base::TimeTicks::Now(); } void UserActivityDetector::ProcessReceivedEvent(const ui::Event* event) { if (!event) return; if (event->IsMouseEvent() || event->IsMouseWheelEvent()) { if (event->flags() & ui::EF_IS_SYNTHESIZED) return; if (!honor_mouse_events_time_.is_null() && GetCurrentTime() < honor_mouse_events_time_) return; } HandleActivity(event); } void UserActivityDetector::HandleActivity(const ui::Event* event) { base::TimeTicks now = GetCurrentTime(); last_activity_time_ = now; if (last_observer_notification_time_.is_null() || (now - last_observer_notification_time_).InMillisecondsF() >= kNotifyIntervalMs) { if (VLOG_IS_ON(1)) VLOG(1) << "Reporting user activity: " << GetEventDebugString(event); FOR_EACH_OBSERVER(UserActivityObserver, observers_, OnUserActivity(event)); last_observer_notification_time_ = now; } } } // namespace ui