blob: 37d9e623edacb1542caa35493898fc24bf06c186 [file] [log] [blame]
// Copyright 2022 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/color_enhancement/color_enhancement_controller.h"
#include "ash/shell.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/compositor/layer.h"
namespace ash {
namespace {
// Sepia filter above .3 should enable cursor compositing. Beyond this point,
// users can perceive the mouse is too white if compositing does not occur.
// TODO (crbug.com/1031959): Check this value with UX to see if it can be
// larger.
const float kMinSepiaPerceptableDifference = 0.3f;
} // namespace
ColorEnhancementController::ColorEnhancementController() {
Shell::Get()->AddShellObserver(this);
}
ColorEnhancementController::~ColorEnhancementController() {
Shell::Get()->RemoveShellObserver(this);
}
void ColorEnhancementController::SetHighContrastEnabled(bool enabled) {
if (high_contrast_enabled_ == enabled)
return;
high_contrast_enabled_ = enabled;
// Enable cursor compositing so the cursor is also inverted.
Shell::Get()->UpdateCursorCompositingEnabled();
UpdateAllDisplays();
}
void ColorEnhancementController::SetGreyscaleAmount(float amount) {
if (greyscale_amount_ == amount || amount < 0 || amount > 1)
return;
greyscale_amount_ = amount;
// Note: No need to do cursor compositing since cursors are greyscale already.
UpdateAllDisplays();
}
void ColorEnhancementController::SetSaturationAmount(float amount) {
if (saturation_amount_ == amount || amount < 0)
return;
saturation_amount_ = amount;
// Note: No need to do cursor compositing since cursors are greyscale and not
// impacted by saturation.
UpdateAllDisplays();
}
void ColorEnhancementController::SetSepiaAmount(float amount) {
if (sepia_amount_ == amount || amount < 0 || amount > 1)
return;
sepia_amount_ = amount;
// The cursor should be tinted sepia as well. Update cursor compositing.
Shell::Get()->UpdateCursorCompositingEnabled();
UpdateAllDisplays();
}
void ColorEnhancementController::SetHueRotationAmount(int amount) {
if (hue_rotation_amount_ == amount || amount < 0 || amount > 359)
return;
hue_rotation_amount_ = amount;
// Note: No need to do cursor compositing since cursors are greyscale and not
// impacted by hue rotation.
UpdateAllDisplays();
}
bool ColorEnhancementController::ShouldEnableCursorCompositingForSepia() const {
if (!::features::
AreExperimentalAccessibilityColorEnhancementSettingsEnabled()) {
return false;
}
// Enable cursor compositing if the sepia filter is on enough that
// the white mouse cursor stands out. Sepia will not be set on the root
// window if the setting value is greater than 1, so ignore that state.
return sepia_amount_ >= kMinSepiaPerceptableDifference && sepia_amount_ <= 1;
}
void ColorEnhancementController::OnRootWindowAdded(aura::Window* root_window) {
UpdateDisplay(root_window);
}
void ColorEnhancementController::UpdateAllDisplays() {
for (auto* root_window : Shell::GetAllRootWindows())
UpdateDisplay(root_window);
}
void ColorEnhancementController::UpdateDisplay(aura::Window* root_window) {
ui::Layer* layer = root_window->layer();
layer->SetLayerInverted(high_contrast_enabled_);
if (!::features::
AreExperimentalAccessibilityColorEnhancementSettingsEnabled()) {
return;
}
layer->SetLayerGrayscale(greyscale_amount_);
layer->SetLayerSaturation(saturation_amount_);
layer->SetLayerSepia(sepia_amount_);
layer->SetLayerHueRotation(hue_rotation_amount_);
// TODO(crbug.com/1031959): Use SetLayerCustomColorMatrix to create color
// filters for common color blindness types.
}
} // namespace ash