blob: 9fbe5998bb390bce5464fdff692b3a42f2323e96 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/input_device_settings/input_device_settings_dispatcher.h"
#include "ash/constants/ash_features.h"
#include "ash/public/mojom/input_device_settings.mojom.h"
#include "ash/shell.h"
#include "ash/system/input_device_settings/input_device_settings_controller_impl.h"
#include "ui/ozone/public/input_controller.h"
namespace ash {
namespace {
bool ShouldModifiersBeBlockedForKeyEventsWithRestriction(
mojom::CustomizationRestriction customization_restriction) {
switch (customization_restriction) {
case mojom::CustomizationRestriction::kAllowCustomizations:
case mojom::CustomizationRestriction::kDisallowCustomizations:
case mojom::CustomizationRestriction::kDisableKeyEventRewrites:
case mojom::CustomizationRestriction::kAllowAlphabetKeyEventRewrites:
case mojom::CustomizationRestriction::
kAllowAlphabetOrNumberKeyEventRewrites:
case mojom::CustomizationRestriction::kAllowHorizontalScrollWheelRewrites:
case mojom::CustomizationRestriction::kAllowFKeyRewrites:
return false;
case mojom::CustomizationRestriction::kAllowTabEventRewrites:
return true;
}
}
} // namespace
InputDeviceSettingsDispatcher::InputDeviceSettingsDispatcher(
ui::InputController* input_controller)
: input_controller_(input_controller) {
input_device_settings_controller_ =
Shell::Get()->input_device_settings_controller();
input_device_settings_controller_->AddObserver(this);
if (features::IsPeripheralCustomizationEnabled()) {
duplicate_id_finder_ =
&input_device_settings_controller_->duplicate_id_finder();
duplicate_id_finder_->AddObserver(this);
}
}
InputDeviceSettingsDispatcher::~InputDeviceSettingsDispatcher() {
input_device_settings_controller_->RemoveObserver(this);
if (features::IsPeripheralCustomizationEnabled()) {
duplicate_id_finder_->RemoveObserver(this);
}
}
void InputDeviceSettingsDispatcher::OnMouseConnected(
const mojom::Mouse& mouse) {
DispatchMouseSettings(mouse);
}
void InputDeviceSettingsDispatcher::OnMouseSettingsUpdated(
const mojom::Mouse& mouse) {
DispatchMouseSettings(mouse);
}
void InputDeviceSettingsDispatcher::OnTouchpadConnected(
const mojom::Touchpad& touchpad) {
DispatchTouchpadSettings(touchpad);
}
void InputDeviceSettingsDispatcher::OnTouchpadSettingsUpdated(
const mojom::Touchpad& touchpad) {
DispatchTouchpadSettings(touchpad);
}
void InputDeviceSettingsDispatcher::OnPointingStickConnected(
const mojom::PointingStick& pointing_stick) {
DispatchPointingStickSettings(pointing_stick);
}
void InputDeviceSettingsDispatcher::OnPointingStickSettingsUpdated(
const mojom::PointingStick& pointing_stick) {
DispatchPointingStickSettings(pointing_stick);
}
void InputDeviceSettingsDispatcher::DispatchMouseSettings(
const mojom::Mouse& mouse) {
DCHECK(mouse.settings);
const auto& settings = *mouse.settings;
input_controller_->SetMouseAcceleration(mouse.id,
settings.acceleration_enabled);
input_controller_->SetMouseSensitivity(mouse.id, settings.sensitivity);
input_controller_->SetMouseReverseScroll(mouse.id,
settings.reverse_scrolling);
input_controller_->SetMouseScrollAcceleration(mouse.id,
settings.scroll_acceleration);
input_controller_->SetMouseScrollSensitivity(mouse.id,
settings.scroll_sensitivity);
input_controller_->SetPrimaryButtonRight(mouse.id, settings.swap_right);
if (!features::IsPeripheralCustomizationEnabled()) {
return;
}
UpdateDevicesToBlockModifiers();
}
void InputDeviceSettingsDispatcher::DispatchTouchpadSettings(
const mojom::Touchpad& touchpad) {
DCHECK(touchpad.settings);
const auto& settings = *touchpad.settings;
input_controller_->SetTouchpadSensitivity(touchpad.id, settings.sensitivity);
input_controller_->SetTouchpadScrollSensitivity(touchpad.id,
settings.scroll_sensitivity);
input_controller_->SetTapToClick(touchpad.id, settings.tap_to_click_enabled);
input_controller_->SetTapDragging(touchpad.id, settings.tap_dragging_enabled);
input_controller_->SetNaturalScroll(touchpad.id, settings.reverse_scrolling);
input_controller_->SetTouchpadAcceleration(touchpad.id,
settings.acceleration_enabled);
input_controller_->SetTouchpadScrollAcceleration(
touchpad.id, settings.scroll_acceleration);
input_controller_->SetTouchpadHapticClickSensitivity(
touchpad.id, settings.haptic_sensitivity);
input_controller_->SetTouchpadHapticFeedback(touchpad.id,
settings.haptic_enabled);
}
void InputDeviceSettingsDispatcher::DispatchPointingStickSettings(
const mojom::PointingStick& pointing_stick) {
DCHECK(pointing_stick.settings);
const auto& settings = *pointing_stick.settings;
input_controller_->SetPointingStickAcceleration(
pointing_stick.id, settings.acceleration_enabled);
input_controller_->SetPointingStickSensitivity(pointing_stick.id,
settings.sensitivity);
input_controller_->SetPointingStickPrimaryButtonRight(pointing_stick.id,
settings.swap_right);
}
void InputDeviceSettingsDispatcher::UpdateDevicesToBlockModifiers() {
devices_with_blocked_modifiers_.clear();
auto mice = input_device_settings_controller_->GetConnectedMice();
for (const auto& mouse : mice) {
if (!ShouldModifiersBeBlockedForKeyEventsWithRestriction(
mouse->customization_restriction)) {
continue;
}
bool block_current_mouse = false;
for (const auto& button_remapping : mouse->settings->button_remappings) {
if (button_remapping->button->is_customizable_button()) {
continue;
}
// If the action is supposed to be "default", do nothing
if (button_remapping->remapping_action.is_null()) {
continue;
}
block_current_mouse = true;
break;
}
if (!block_current_mouse) {
continue;
}
auto vid_pid = duplicate_id_finder_->GetVendorProductIdForDevice(mouse->id);
if (!vid_pid) {
continue;
}
devices_with_blocked_modifiers_.insert(*vid_pid);
}
DispatchDevicesToBlockModifiers();
}
void InputDeviceSettingsDispatcher::OnDuplicateDevicesUpdated() {
DispatchDevicesToBlockModifiers();
}
void InputDeviceSettingsDispatcher::DispatchDevicesToBlockModifiers() {
std::vector<int> device_ids;
for (const auto& vid_pid : devices_with_blocked_modifiers_) {
auto* duplicate_ids = duplicate_id_finder_->GetDuplicateDeviceIds(vid_pid);
if (!duplicate_ids) {
continue;
}
device_ids.reserve(device_ids.size() + duplicate_ids->size());
device_ids.insert(device_ids.end(), duplicate_ids->begin(),
duplicate_ids->end());
}
// Insert devices from `devices_with_blocked_modifiers_from_observing_` but
// check to make sure we are not duplicating anything.
for (const auto& vid_pid : devices_with_blocked_modifiers_from_observing_) {
if (devices_with_blocked_modifiers_.contains(vid_pid)) {
continue;
}
auto* duplicate_ids = duplicate_id_finder_->GetDuplicateDeviceIds(vid_pid);
if (!duplicate_ids) {
continue;
}
device_ids.reserve(device_ids.size() + duplicate_ids->size());
device_ids.insert(device_ids.end(), duplicate_ids->begin(),
duplicate_ids->end());
}
input_controller_->BlockModifiersOnDevices(std::move(device_ids));
}
void InputDeviceSettingsDispatcher::OnCustomizableMouseObservingStarted(
const mojom::Mouse& mouse) {
if (!ShouldModifiersBeBlockedForKeyEventsWithRestriction(
mouse.customization_restriction)) {
return;
}
auto vid_pid = duplicate_id_finder_->GetVendorProductIdForDevice(mouse.id);
if (!vid_pid) {
return;
}
devices_with_blocked_modifiers_from_observing_.insert(*vid_pid);
DispatchDevicesToBlockModifiers();
}
void InputDeviceSettingsDispatcher::OnCustomizableMouseObservingStopped() {
if (devices_with_blocked_modifiers_from_observing_.empty()) {
return;
}
devices_with_blocked_modifiers_from_observing_.clear();
DispatchDevicesToBlockModifiers();
}
} // namespace ash