Enabled/disable touch screen in TabletPowerButtonController
By exposing several apis in input_device_settings.h and add new local pref for TouchScreenEnabled, we can disable touch screen events when backlights are forced off so that no screen UI events can be triggered and enable touch screen when stopping backlights forced off is called properly.
BUG=655388
BUG=633304
TEST=manual test on device, and add test coverage.
also test that this added behavior is compatible with toggle touchscreen shortcut
The shortcut induced in https://codereview.chromium.org/2467023004 is per user pref, backlights-forced-off related touch screen status is per device pref. The final hardware touchscreen status is determined by the rule: enabled_in_local_state && enabled_in_user_pref
Review-Url: https://codereview.chromium.org/2533373002
Cr-Commit-Position: refs/heads/master@{#436177}
diff --git a/ash/common/accelerators/debug_commands.cc b/ash/common/accelerators/debug_commands.cc
index fc5270b..b3ea038 100644
--- a/ash/common/accelerators/debug_commands.cc
+++ b/ash/common/accelerators/debug_commands.cc
@@ -128,7 +128,11 @@
void HandleToggleTouchscreen() {
base::RecordAction(base::UserMetricsAction("Accel_Toggle_Touchscreen"));
- ash::WmShell::Get()->delegate()->ToggleTouchscreen();
+ ShellDelegate* delegate = WmShell::Get()->delegate();
+ delegate->SetTouchscreenEnabledInPrefs(
+ !delegate->IsTouchscreenEnabledInPrefs(false /* use_local_state */),
+ false /* use_local_state */);
+ delegate->UpdateTouchscreenStatusFromPrefs();
}
void HandleToggleTouchView() {
diff --git a/ash/common/shell_delegate.h b/ash/common/shell_delegate.h
index 27d59cf..d95f49ac 100644
--- a/ash/common/shell_delegate.h
+++ b/ash/common/shell_delegate.h
@@ -133,9 +133,21 @@
virtual gfx::Image GetDeprecatedAcceleratorImage() const = 0;
- // Toggles the status of the touchpad / touchscreen on or off.
+ // If |use_local_state| is true, returns the touchscreen status from local
+ // state, otherwise from user prefs.
+ virtual bool IsTouchscreenEnabledInPrefs(bool use_local_state) const = 0;
+
+ // Sets the status of touchscreen to |enabled| in prefs. If |use_local_state|,
+ // pref is set in local state, otherwise in user prefs.
+ virtual void SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) = 0;
+
+ // Updates the enabled/disabled status of the touchscreen from prefs. Enabled
+ // if both local state and user prefs are enabled, otherwise disabled.
+ virtual void UpdateTouchscreenStatusFromPrefs() = 0;
+
+ // Toggles the status of touchpad between enabled and disabled.
virtual void ToggleTouchpad() {}
- virtual void ToggleTouchscreen() {}
};
} // namespace ash
diff --git a/ash/mus/shell_delegate_mus.cc b/ash/mus/shell_delegate_mus.cc
index 3e2dc1c6..054100e 100644
--- a/ash/mus/shell_delegate_mus.cc
+++ b/ash/mus/shell_delegate_mus.cc
@@ -231,4 +231,18 @@
return gfx::Image();
}
+bool ShellDelegateMus::IsTouchscreenEnabledInPrefs(bool use_local_state) const {
+ NOTIMPLEMENTED();
+ return true;
+}
+
+void ShellDelegateMus::SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) {
+ NOTIMPLEMENTED();
+}
+
+void ShellDelegateMus::UpdateTouchscreenStatusFromPrefs() {
+ NOTIMPLEMENTED();
+}
+
} // namespace ash
diff --git a/ash/mus/shell_delegate_mus.h b/ash/mus/shell_delegate_mus.h
index dd88827..81e6701 100644
--- a/ash/mus/shell_delegate_mus.h
+++ b/ash/mus/shell_delegate_mus.h
@@ -47,6 +47,10 @@
GPUSupport* CreateGPUSupport() override;
base::string16 GetProductName() const override;
gfx::Image GetDeprecatedAcceleratorImage() const override;
+ bool IsTouchscreenEnabledInPrefs(bool use_local_state) const override;
+ void SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) override;
+ void UpdateTouchscreenStatusFromPrefs() override;
private:
service_manager::Connector* connector_;
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index 76e340fa..b9c7c01 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -265,5 +265,15 @@
return gfx::Image();
}
+bool ShellDelegateImpl::IsTouchscreenEnabledInPrefs(
+ bool use_local_state) const {
+ return true;
+}
+
+void ShellDelegateImpl::SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) {}
+
+void ShellDelegateImpl::UpdateTouchscreenStatusFromPrefs() {}
+
} // namespace shell
} // namespace ash
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index 073d366..590da66 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -53,6 +53,10 @@
GPUSupport* CreateGPUSupport() override;
base::string16 GetProductName() const override;
gfx::Image GetDeprecatedAcceleratorImage() const override;
+ bool IsTouchscreenEnabledInPrefs(bool use_local_state) const override;
+ void SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) override;
+ void UpdateTouchscreenStatusFromPrefs() override;
private:
ShelfDelegate* shelf_delegate_;
diff --git a/ash/system/chromeos/power/tablet_power_button_controller.cc b/ash/system/chromeos/power/tablet_power_button_controller.cc
index bd52b98..66841d16 100644
--- a/ash/system/chromeos/power/tablet_power_button_controller.cc
+++ b/ash/system/chromeos/power/tablet_power_button_controller.cc
@@ -6,6 +6,7 @@
#include "ash/common/accessibility_delegate.h"
#include "ash/common/session/session_state_delegate.h"
+#include "ash/common/shell_delegate.h"
#include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
#include "ash/common/wm_shell.h"
#include "ash/shell.h"
@@ -96,24 +97,27 @@
// backlight has been turned back on before seeing the power button events
// that woke the system. Ignore events just after resuming to ensure that we
// don't turn the screen off in response to the events.
+ //
+ // TODO(warx): pressing power button should also StartShutdownTimer() in this
+ // case. Reorganize the code to support that.
if (timestamp - last_resume_time_ <=
base::TimeDelta::FromMilliseconds(kIgnorePowerButtonAfterResumeMs)) {
// If backlights are forced off, stop forcing off because resuming system
// doesn't handle this.
if (down && backlights_forced_off_)
- SetBacklightsForcedOff(false);
+ SetDisplayForcedOff(false);
return;
}
if (down) {
screen_off_when_power_button_down_ = brightness_level_is_zero_;
- SetBacklightsForcedOff(false);
+ SetDisplayForcedOff(false);
StartShutdownTimer();
} else {
if (shutdown_timer_.IsRunning()) {
shutdown_timer_.Stop();
if (!screen_off_when_power_button_down_) {
- SetBacklightsForcedOff(true);
+ SetDisplayForcedOff(true);
LockScreenIfRequired();
}
}
@@ -149,7 +153,7 @@
return;
if (!IsTabletModeActive() && backlights_forced_off_)
- SetBacklightsForcedOff(false);
+ SetDisplayForcedOff(false);
}
void TabletPowerButtonController::OnMouseEvent(ui::MouseEvent* event) {
@@ -161,13 +165,13 @@
}
if (!IsTabletModeActive() && backlights_forced_off_)
- SetBacklightsForcedOff(false);
+ SetDisplayForcedOff(false);
}
void TabletPowerButtonController::OnStylusStateChanged(ui::StylusState state) {
if (IsTabletModeSupported() && state == ui::StylusState::REMOVED &&
backlights_forced_off_) {
- SetBacklightsForcedOff(false);
+ SetDisplayForcedOff(false);
}
}
@@ -177,15 +181,21 @@
tick_clock_ = std::move(tick_clock);
}
-void TabletPowerButtonController::SetBacklightsForcedOff(bool forced_off) {
+void TabletPowerButtonController::SetDisplayForcedOff(bool forced_off) {
if (backlights_forced_off_ == forced_off)
return;
+ // Set the display and keyboard backlights (if present) to |forced_off|.
chromeos::DBusThreadManager::Get()
->GetPowerManagerClient()
->SetBacklightsForcedOff(forced_off);
backlights_forced_off_ = forced_off;
+ ShellDelegate* delegate = WmShell::Get()->delegate();
+ delegate->SetTouchscreenEnabledInPrefs(!forced_off,
+ true /* use_local_state */);
+ delegate->UpdateTouchscreenStatusFromPrefs();
+
// Send an a11y alert.
WmShell::Get()->accessibility_delegate()->TriggerAccessibilityAlert(
forced_off ? A11Y_ALERT_SCREEN_OFF : A11Y_ALERT_SCREEN_ON);
diff --git a/ash/system/chromeos/power/tablet_power_button_controller.h b/ash/system/chromeos/power/tablet_power_button_controller.h
index 66a5b61d..f59749d 100644
--- a/ash/system/chromeos/power/tablet_power_button_controller.h
+++ b/ash/system/chromeos/power/tablet_power_button_controller.h
@@ -72,8 +72,10 @@
void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
private:
- // Set backlights to |forced_off| if they aren't already.
- void SetBacklightsForcedOff(bool forced_off);
+ // Updates the power manager's backlights-forced-off state and enables or
+ // disables the touchscreen. No-op if |backlights_forced_off_| already equals
+ // |forced_off|.
+ void SetDisplayForcedOff(bool forced_off);
// Sends a request to powerd to get the backlights forced off state so that
// |backlights_forced_off_| can be initialized.
diff --git a/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc b/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc
index 4633032..a27af600 100644
--- a/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc
+++ b/ash/system/chromeos/power/tablet_power_button_controller_unittest.cc
@@ -13,6 +13,7 @@
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/lock_state_controller_test_api.h"
+#include "ash/test/test_shell_delegate.h"
#include "ash/wm/lock_state_controller.h"
#include "ash/wm/power_button_controller.h"
#include "base/command_line.h"
@@ -64,6 +65,8 @@
tick_clock_ = new base::SimpleTestTickClock;
tablet_controller_->SetTickClockForTesting(
std::unique_ptr<base::TickClock>(tick_clock_));
+ shell_delegate_ =
+ static_cast<TestShellDelegate*>(WmShell::Get()->delegate());
generator_ = &AshTestBase::GetEventGenerator();
power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, false);
EXPECT_FALSE(GetBacklightsForcedOff());
@@ -119,6 +122,7 @@
TabletPowerButtonController* tablet_controller_; // Not owned.
std::unique_ptr<TabletPowerButtonController::TestApi> test_api_;
base::SimpleTestTickClock* tick_clock_; // Not owned.
+ TestShellDelegate* shell_delegate_; // Not owned.
ui::test::EventGenerator* generator_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TabletPowerButtonControllerTest);
@@ -356,5 +360,43 @@
EXPECT_EQ(1, power_manager_client_->num_set_backlights_forced_off_calls());
}
+// Tests that under (1) tablet power button pressed/released, (2) keyboard/mouse
+// events on laptop mode when screen is off, requesting/stopping backlights
+// forced off should also set corresponding touch screen state in local pref.
+TEST_F(TabletPowerButtonControllerTest, TouchScreenState) {
+ // Tests tablet power button.
+ EXPECT_TRUE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+ PressPowerButton();
+ ReleasePowerButton();
+ power_manager_client_->SendBrightnessChanged(0, false);
+ EXPECT_FALSE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+
+ PressPowerButton();
+ power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, false);
+ ReleasePowerButton();
+ EXPECT_TRUE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+
+ EnableMaximizeMode(false);
+ // KeyEvent on laptop mode when screen is off.
+ PressPowerButton();
+ ReleasePowerButton();
+ power_manager_client_->SendBrightnessChanged(0, false);
+ EXPECT_TRUE(GetBacklightsForcedOff());
+ EXPECT_FALSE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+ generator_->PressKey(ui::VKEY_L, ui::EF_NONE);
+ power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, false);
+ EXPECT_TRUE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+
+ // MouseEvent on laptop mode when screen is off.
+ PressPowerButton();
+ ReleasePowerButton();
+ power_manager_client_->SendBrightnessChanged(0, false);
+ EXPECT_TRUE(GetBacklightsForcedOff());
+ EXPECT_FALSE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+ generator_->MoveMouseBy(1, 1);
+ power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, false);
+ EXPECT_TRUE(shell_delegate_->IsTouchscreenEnabledInPrefs(true));
+}
+
} // namespace test
} // namespace ash
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index 8e2fcea..d91c644 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -86,6 +86,7 @@
: num_exit_requests_(0),
multi_profiles_enabled_(false),
force_maximize_on_first_run_(false),
+ touchscreen_enabled_in_local_pref_(true),
app_list_presenter_delegate_factory_(new AppListPresenterDelegateFactory(
base::WrapUnique(new AppListViewDelegateFactoryImpl))) {}
@@ -184,6 +185,19 @@
return gfx::Image();
}
+bool TestShellDelegate::IsTouchscreenEnabledInPrefs(
+ bool use_local_state) const {
+ return use_local_state ? touchscreen_enabled_in_local_pref_ : true;
+}
+
+void TestShellDelegate::SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) {
+ if (use_local_state)
+ touchscreen_enabled_in_local_pref_ = enabled;
+}
+
+void TestShellDelegate::UpdateTouchscreenStatusFromPrefs() {}
+
void TestShellDelegate::SetMediaCaptureState(MediaCaptureState state) {
#if defined(OS_CHROMEOS)
static_cast<MediaDelegateImpl*>(WmShell::Get()->media_delegate())
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index 143fa14..b3aee0c5 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -60,6 +60,11 @@
base::string16 GetProductName() const override;
gfx::Image GetDeprecatedAcceleratorImage() const override;
+ bool IsTouchscreenEnabledInPrefs(bool use_local_state) const override;
+ void SetTouchscreenEnabledInPrefs(bool enabled,
+ bool use_local_state) override;
+ void UpdateTouchscreenStatusFromPrefs() override;
+
int num_exit_requests() const { return num_exit_requests_; }
app_list::AppListPresenterImpl* app_list_presenter() {
@@ -75,6 +80,7 @@
int num_exit_requests_;
bool multi_profiles_enabled_;
bool force_maximize_on_first_run_;
+ bool touchscreen_enabled_in_local_pref_;
std::unique_ptr<app_list::AppListPresenterDelegateFactory>
app_list_presenter_delegate_factory_;