Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Unified Diff: ash/system/chromeos/power/tablet_power_button_controller.cc

Issue 2474913004: Tablet-like power button behavior on Convertible/Tablet ChromeOS devices (Closed)
Patch Set: cr and additional changes Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ash/system/chromeos/power/tablet_power_button_controller.cc
diff --git a/ash/system/chromeos/power/tablet_power_button_controller.cc b/ash/system/chromeos/power/tablet_power_button_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a07475764a9c034cf8bb6ade5993e81a36a0dd75
--- /dev/null
+++ b/ash/system/chromeos/power/tablet_power_button_controller.cc
@@ -0,0 +1,216 @@
+// Copyright 2016 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 "ash/system/chromeos/power/tablet_power_button_controller.h"
+
+#include "ash/common/session/session_state_delegate.h"
+#include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
+#include "ash/common/wm_shell.h"
+#include "ash/shell.h"
+#include "ash/wm/lock_state_controller.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "ui/events/devices/input_device_manager.h"
+#include "ui/events/devices/stylus_state.h"
+#include "ui/events/event.h"
+
+namespace ash {
+
+namespace {
+
+// Amount of time the power button must be held to start the pre-shutdown
+// animation when in tablet mode.
+constexpr int kShutdownTimeoutMs = 1000;
+
+// Amount of time since last SuspendDone() that power button event needs to be
+// ignored.
+constexpr int kWaitSuspendDoneDurationMs = 2000;
Daniel Erat 2016/11/10 22:48:55 nit: kIgnorePowerButtonAfterResumeMs?
Qiang(Joe) Xu 2016/11/11 04:39:22 Done.
+
+TabletPowerButtonController* instance = nullptr;
+
+// Returns true if device is a convertible/tablet device or has
+// kAshEnableTouchViewTesting in test, otherwise false.
+bool IsTabletModeSupported() {
+ MaximizeModeController* maximize_mode_controller =
+ WmShell::Get()->maximize_mode_controller();
+ return maximize_mode_controller &&
+ maximize_mode_controller->CanEnterMaximizeMode();
+}
+
+// Returns true if device is currently in tablet/maximize mode, otherwise false.
+bool IsTabletModeActive() {
+ MaximizeModeController* maximize_mode_controller =
+ WmShell::Get()->maximize_mode_controller();
+ return maximize_mode_controller &&
+ maximize_mode_controller->IsMaximizeModeWindowManagerEnabled();
+}
+
+} // namespace
+
+TabletPowerButtonController::TestApi::TestApi(
+ TabletPowerButtonController* controller)
+ : controller_(controller) {}
+
+TabletPowerButtonController::TestApi::~TestApi() {}
+
+bool TabletPowerButtonController::TestApi::ShutdownTimerIsRunning() const {
+ return controller_->shutdown_timer_.IsRunning();
+}
+
+void TabletPowerButtonController::TestApi::TriggerShutdownTimeout() {
+ DCHECK(ShutdownTimerIsRunning());
Daniel Erat 2016/11/10 22:48:54 how about making this method return false if the t
Qiang(Joe) Xu 2016/11/11 04:39:22 EXPECT_FALSE(TriggerShutdownTimeout) can represent
+ controller_->OnShutdownTimeout();
+ controller_->shutdown_timer_.Stop();
+}
+
+// static
+TabletPowerButtonController* TabletPowerButtonController::GetInstance() {
+ DCHECK(instance);
+ return instance;
+}
+
+TabletPowerButtonController::TabletPowerButtonController(
+ LockStateController* controller)
+ : controller_(controller) {
+ DCHECK(!instance);
+ instance = this;
+
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
+ this);
+ ui::InputDeviceManager::GetInstance()->AddObserver(this);
+ Shell::GetInstance()->PrependPreTargetHandler(this);
+ GetInitialBacklightsForcedOff();
+}
+
+TabletPowerButtonController::~TabletPowerButtonController() {
+ Shell::GetInstance()->RemovePreTargetHandler(this);
+ ui::InputDeviceManager::GetInstance()->RemoveObserver(this);
+ chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
+ this);
+
+ DCHECK_EQ(instance, this);
+ instance = nullptr;
+}
+
+bool TabletPowerButtonController::ShouldHandlePowerButtonEvents() const {
+ return IsTabletModeSupported();
+}
+
+void TabletPowerButtonController::OnPowerButtonEvent(
+ bool down,
+ const base::TimeTicks& timestamp) {
+ // When pressing power button causing SuspendDone, chrome side will first
Daniel Erat 2016/11/10 22:48:55 how about this? // When the system resumes in res
Qiang(Joe) Xu 2016/11/11 04:39:22 It is much better. Thanks!
+ // receive SuspendDone signal and then power button events. The resumed
+ // brightness could make chrome think it is pressed on brightness-on-state,
+ // but actually it is pressed on suspended-state (brightness-off-state).
+ if (!last_resume_time_.is_null() &&
+ timestamp - last_resume_time_ <=
+ base::TimeDelta::FromMilliseconds(kWaitSuspendDoneDurationMs)) {
+ return;
+ }
+
+ if (down) {
+ screen_off_when_power_button_down_ = brightness_level_is_zero_;
+ SetBacklightsForcedOff(false);
+ StartShutdownTimer();
+ } else {
+ if (shutdown_timer_.IsRunning()) {
+ shutdown_timer_.Stop();
+ if (!screen_off_when_power_button_down_) {
+ SetBacklightsForcedOff(true);
+ LockScreenIfRequired();
+ }
+ }
+ screen_off_when_power_button_down_ = false;
+
+ // When power button is released, cancel shutdown animation whenever it is
+ // still cancellable.
+ if (controller_->CanCancelShutdownAnimation())
+ controller_->CancelShutdownAnimation();
+ }
+}
+
+void TabletPowerButtonController::PowerManagerRestarted() {
+ chromeos::DBusThreadManager::Get()
+ ->GetPowerManagerClient()
+ ->SetBacklightsForcedOff(backlights_forced_off_);
+}
+
+void TabletPowerButtonController::BrightnessChanged(int level,
+ bool user_initiated) {
+ brightness_level_is_zero_ = level == 0;
+}
+
+void TabletPowerButtonController::SuspendDone(
+ const base::TimeDelta& sleep_duration) {
+ last_resume_time_ = base::TimeTicks::Now();
Daniel Erat 2016/11/10 22:48:54 i'd suggest using base::TickClock instead so you c
Qiang(Joe) Xu 2016/11/11 04:39:22 Done.
+}
+
+void TabletPowerButtonController::OnKeyEvent(ui::KeyEvent* event) {
+ if (!IsTabletModeActive() && backlights_forced_off_)
+ SetBacklightsForcedOff(false);
+}
+
+void TabletPowerButtonController::OnMouseEvent(ui::MouseEvent* event) {
+ ui::EventPointerType pointer_type = event->pointer_details().pointer_type;
+ if (pointer_type != ui::EventPointerType::POINTER_TYPE_MOUSE &&
+ pointer_type != ui::EventPointerType::POINTER_TYPE_TOUCH) {
+ return;
+ }
+
+ if (!IsTabletModeActive() && backlights_forced_off_)
+ SetBacklightsForcedOff(false);
+}
+
+void TabletPowerButtonController::OnStylusStateChanged(ui::StylusState state) {
+ if (IsTabletModeSupported() && state == ui::StylusState::REMOVED &&
+ backlights_forced_off_) {
+ SetBacklightsForcedOff(false);
+ }
+}
+
+void TabletPowerButtonController::SetBacklightsForcedOff(bool forced_off) {
+ if (backlights_forced_off_ == forced_off)
+ return;
+
+ chromeos::DBusThreadManager::Get()
+ ->GetPowerManagerClient()
+ ->SetBacklightsForcedOff(forced_off);
+ backlights_forced_off_ = forced_off;
+}
+
+void TabletPowerButtonController::GetInitialBacklightsForcedOff() {
+ chromeos::DBusThreadManager::Get()
+ ->GetPowerManagerClient()
+ ->GetBacklightsForcedOff(base::Bind(
+ &TabletPowerButtonController::OnGotInitialBacklightsForcedOff,
+ base::Unretained(this)));
+}
+
+void TabletPowerButtonController::OnGotInitialBacklightsForcedOff(
+ bool is_forced_off) {
+ backlights_forced_off_ = is_forced_off;
+}
+
+void TabletPowerButtonController::StartShutdownTimer() {
+ shutdown_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
+ this, &TabletPowerButtonController::OnShutdownTimeout);
+}
+
+void TabletPowerButtonController::OnShutdownTimeout() {
+ controller_->StartShutdownAnimation();
+}
+
+void TabletPowerButtonController::LockScreenIfRequired() {
+ SessionStateDelegate* session_state_delegate =
+ WmShell::Get()->GetSessionStateDelegate();
+ if (session_state_delegate->ShouldLockScreenAutomatically() &&
+ session_state_delegate->CanLockScreen() &&
+ !session_state_delegate->IsUserSessionBlocked() &&
+ !controller_->LockRequested()) {
+ session_state_delegate->LockScreen();
+ }
+}
+
+} // namespace ash

Powered by Google App Engine
This is Rietveld 408576698