blob: 161ca3c666096c06d5c35c14e0f2890013636e07 [file] [log] [blame]
// Copyright 2017 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/touch/touch_devices_controller.h"
#include <utility>
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "services/ws/public/cpp/input_devices/input_device_controller_client.h"
#include "ui/wm/core/cursor_manager.h"
namespace ash {
namespace {
void OnSetTouchpadEnabledDone(bool enabled, bool succeeded) {
// Don't log here, |succeeded| is only true if there is a touchpad *and* the
// value changed. In other words |succeeded| is false when not on device or
// the value was already at the value specified. Neither of these are
// interesting failures.
if (!succeeded)
return;
::wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
if (!cursor_manager)
return;
if (enabled)
cursor_manager->ShowCursor();
else
cursor_manager->HideCursor();
}
ws::InputDeviceControllerClient* GetInputDeviceControllerClient() {
return Shell::Get()->shell_delegate()->GetInputDeviceControllerClient();
}
PrefService* GetActivePrefService() {
return Shell::Get()->session_controller()->GetActivePrefService();
}
} // namespace
// static
void TouchDevicesController::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(
prefs::kTapDraggingEnabled, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF |
PrefRegistry::PUBLIC);
registry->RegisterBooleanPref(prefs::kTouchpadEnabled, PrefRegistry::PUBLIC);
registry->RegisterBooleanPref(prefs::kTouchscreenEnabled,
PrefRegistry::PUBLIC);
}
TouchDevicesController::TouchDevicesController() {
Shell::Get()->session_controller()->AddObserver(this);
}
TouchDevicesController::~TouchDevicesController() {
Shell::Get()->session_controller()->RemoveObserver(this);
}
void TouchDevicesController::ToggleTouchpad() {
PrefService* prefs = GetActivePrefService();
if (!prefs)
return;
const bool touchpad_enabled = prefs->GetBoolean(prefs::kTouchpadEnabled);
prefs->SetBoolean(prefs::kTouchpadEnabled, !touchpad_enabled);
}
bool TouchDevicesController::GetTouchpadEnabled(
TouchDeviceEnabledSource source) const {
if (source == TouchDeviceEnabledSource::GLOBAL)
return global_touchpad_enabled_;
PrefService* prefs = GetActivePrefService();
return prefs && prefs->GetBoolean(prefs::kTouchpadEnabled);
}
void TouchDevicesController::SetTouchpadEnabled(
bool enabled,
TouchDeviceEnabledSource source) {
if (source == TouchDeviceEnabledSource::GLOBAL) {
global_touchpad_enabled_ = enabled;
UpdateTouchpadEnabled();
return;
}
PrefService* prefs = GetActivePrefService();
if (!prefs)
return;
prefs->SetBoolean(prefs::kTouchpadEnabled, enabled);
}
bool TouchDevicesController::GetTouchscreenEnabled(
TouchDeviceEnabledSource source) const {
if (source == TouchDeviceEnabledSource::GLOBAL)
return global_touchscreen_enabled_;
PrefService* prefs = GetActivePrefService();
return prefs && prefs->GetBoolean(prefs::kTouchscreenEnabled);
}
void TouchDevicesController::SetTouchscreenEnabled(
bool enabled,
TouchDeviceEnabledSource source) {
if (source == TouchDeviceEnabledSource::GLOBAL) {
global_touchscreen_enabled_ = enabled;
// Explicitly call |UpdateTouchscreenEnabled()| to update the actual
// touchscreen state from multiple sources.
UpdateTouchscreenEnabled();
return;
}
PrefService* prefs = GetActivePrefService();
if (!prefs)
return;
prefs->SetBoolean(prefs::kTouchscreenEnabled, enabled);
}
void TouchDevicesController::OnUserSessionAdded(const AccountId& account_id) {
uma_record_callback_ = base::BindOnce([](PrefService* prefs) {
UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Started",
prefs->GetBoolean(prefs::kTapDraggingEnabled));
});
}
void TouchDevicesController::OnSigninScreenPrefServiceInitialized(
PrefService* prefs) {
ObservePrefs(prefs);
}
void TouchDevicesController::OnActiveUserPrefServiceChanged(
PrefService* prefs) {
if (uma_record_callback_)
std::move(uma_record_callback_).Run(prefs);
ObservePrefs(prefs);
}
void TouchDevicesController::ObservePrefs(PrefService* prefs) {
// Watch for pref updates.
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
pref_change_registrar_->Init(prefs);
pref_change_registrar_->Add(
prefs::kTapDraggingEnabled,
base::BindRepeating(&TouchDevicesController::UpdateTapDraggingEnabled,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kTouchpadEnabled,
base::BindRepeating(&TouchDevicesController::UpdateTouchpadEnabled,
base::Unretained(this)));
pref_change_registrar_->Add(
prefs::kTouchscreenEnabled,
base::BindRepeating(&TouchDevicesController::UpdateTouchscreenEnabled,
base::Unretained(this)));
// Load current state.
UpdateTapDraggingEnabled();
UpdateTouchpadEnabled();
UpdateTouchscreenEnabled();
}
void TouchDevicesController::UpdateTapDraggingEnabled() {
PrefService* prefs = GetActivePrefService();
const bool enabled = prefs->GetBoolean(prefs::kTapDraggingEnabled);
if (tap_dragging_enabled_ == enabled)
return;
tap_dragging_enabled_ = enabled;
UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Changed", enabled);
if (!GetInputDeviceControllerClient())
return; // Happens in tests.
GetInputDeviceControllerClient()->SetTapDragging(enabled);
}
void TouchDevicesController::UpdateTouchpadEnabled() {
if (!GetInputDeviceControllerClient())
return; // Happens in tests.
bool enabled = GetTouchpadEnabled(TouchDeviceEnabledSource::GLOBAL) &&
GetTouchpadEnabled(TouchDeviceEnabledSource::USER_PREF);
GetInputDeviceControllerClient()->SetInternalTouchpadEnabled(
enabled, base::BindRepeating(&OnSetTouchpadEnabledDone, enabled));
}
void TouchDevicesController::UpdateTouchscreenEnabled() {
if (!GetInputDeviceControllerClient())
return; // Happens in tests.
GetInputDeviceControllerClient()->SetTouchscreensEnabled(
GetTouchscreenEnabled(TouchDeviceEnabledSource::GLOBAL) &&
GetTouchscreenEnabled(TouchDeviceEnabledSource::USER_PREF));
}
} // namespace ash