blob: 45b8ec134b18d5b4801cce7cf5dc415a13b6c772 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rgbkbd/rgb_keyboard_controller_impl.h"
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/logging.h"
#include "base/notreached.h"
namespace rgbkbd {
RgbKeyboardControllerImpl::RgbKeyboardControllerImpl(RgbKeyboard* keyboard)
: keyboard_(keyboard), background_color_(kWhiteBackgroundColor) {}
RgbKeyboardControllerImpl::~RgbKeyboardControllerImpl() = default;
uint32_t RgbKeyboardControllerImpl::GetRgbKeyboardCapabilities() {
if (!capabilities_.has_value()) {
capabilities_ = keyboard_->GetRgbKeyboardCapabilities();
if (capabilities_.value() == RgbKeyboardCapabilities::kIndividualKey) {
PopulateRainbowModeMap();
}
}
return static_cast<uint32_t>(capabilities_.value());
}
void RgbKeyboardControllerImpl::SetKeyColor(const KeyColor& key_color) {
keyboard_->SetKeyColor(key_color.key, key_color.color.r, key_color.color.g,
key_color.color.b);
}
void RgbKeyboardControllerImpl::SetAllKeyColors(const Color& color) {
keyboard_->SetAllKeyColors(color.r, color.g, color.b);
}
void RgbKeyboardControllerImpl::SetCapsLockState(bool enabled) {
caps_lock_enabled_ = enabled;
// Per zone keyboards can not independently set left/right shift RGB colors.
// TODO(michaelcheco): Prevent this call from happening for per zone keyboards
// higher up in the stack.
if (IsZonedKeyboard()) {
LOG(ERROR) << "Attempted to set caps lock color for a per zone keyboard";
return;
}
SetKeyColor({kLeftShiftKey, GetCurrentCapsLockColor(kLeftShiftKey)});
SetKeyColor({kRightShiftKey, GetCurrentCapsLockColor(kRightShiftKey)});
}
void RgbKeyboardControllerImpl::SetStaticBackgroundColor(uint8_t r,
uint8_t g,
uint8_t b) {
background_type_ = BackgroundType::kStaticSingleColor;
background_color_ = Color(r, g, b);
SetAllKeyColors(background_color_);
// If Capslock was enabled, re-color the highlight keys.
if (caps_lock_enabled_) {
SetCapsLockState(/*caps_lock_enabled_=*/true);
}
}
void RgbKeyboardControllerImpl::SetKeyboardClient(RgbKeyboard* keyboard) {
DCHECK(keyboard);
keyboard_ = keyboard;
}
void RgbKeyboardControllerImpl::SetKeyboardCapabilityForTesting(
RgbKeyboardCapabilities capability) {
capabilities_ = capability;
if (capabilities_.value() == RgbKeyboardCapabilities::kIndividualKey) {
PopulateRainbowModeMap();
} else {
individual_key_rainbow_mode_map_.clear();
}
}
const base::span<const KeyColor>
RgbKeyboardControllerImpl::GetRainbowModeForKeyboard() const {
DCHECK(capabilities_.has_value());
switch (capabilities_.value()) {
case RgbKeyboardCapabilities::kNone:
NOTREACHED();
return base::span<const KeyColor>();
case RgbKeyboardCapabilities::kIndividualKey:
return base::span<const KeyColor>(kRainbowModeIndividualKey,
std::size(kRainbowModeIndividualKey));
case RgbKeyboardCapabilities::kFourZoneFortyLed:
return base::span<const KeyColor>(
kRainbowModeFourZoneFortyLed,
std::size(kRainbowModeFourZoneFortyLed));
case RgbKeyboardCapabilities::kFourZoneTwelveLed:
return base::span<const KeyColor>(
kRainbowModeFourZoneTwelveLed,
std::size(kRainbowModeFourZoneTwelveLed));
case RgbKeyboardCapabilities::kFourZoneFourLed:
return base::span<const KeyColor>(kRainbowModeFourZoneFourLed,
std::size(kRainbowModeFourZoneFourLed));
}
}
void RgbKeyboardControllerImpl::SetRainbowMode() {
background_type_ = BackgroundType::kStaticRainbow;
for (const auto& entry : GetRainbowModeForKeyboard()) {
// Check if caps lock is enabled to avoid overriding the caps lock
// highlight keys.
if (caps_lock_enabled_ && IsShiftKey(entry.key)) {
continue;
}
keyboard_->SetKeyColor(entry.key, entry.color.r, entry.color.g,
entry.color.b);
}
}
// TODO(jimmyxgong): Implement this stub.
void RgbKeyboardControllerImpl::SetAnimationMode(RgbAnimationMode mode) {
NOTIMPLEMENTED();
}
const std::vector<KeyColor>
RgbKeyboardControllerImpl::GetRainbowModeColorsWithoutShiftKeysForTesting() {
DCHECK(capabilities_ == RgbKeyboardCapabilities::kIndividualKey);
std::vector<KeyColor> vec;
for (const auto& entry : kRainbowModeIndividualKey) {
if (entry.key == kLeftShiftKey || entry.key == kRightShiftKey) {
continue;
}
vec.push_back(entry);
}
return vec;
}
Color RgbKeyboardControllerImpl::GetCurrentCapsLockColor(
uint32_t key_idx) const {
if (caps_lock_enabled_) {
return GetCapsLockHighlightColor();
}
if (background_type_ == BackgroundType::kStaticRainbow) {
return GetRainbowColorForKey(key_idx);
}
return background_color_;
}
Color RgbKeyboardControllerImpl::GetCapsLockHighlightColor() const {
return (background_color_ == kWhiteBackgroundColor)
? kCapsLockHighlightAlternate
: kCapsLockHighlightDefault;
}
Color RgbKeyboardControllerImpl::GetRainbowColorForKey(uint32_t key_idx) const {
DCHECK(capabilities_ == RgbKeyboardCapabilities::kIndividualKey);
return individual_key_rainbow_mode_map_.at(key_idx);
}
void RgbKeyboardControllerImpl::PopulateRainbowModeMap() {
std::vector<std::pair<uint32_t, Color>> vec;
vec.reserve(std::size(kRainbowModeIndividualKey));
for (auto i = 0; i < std::size(kRainbowModeIndividualKey); i++) {
vec.push_back(std::make_pair(kRainbowModeIndividualKey[i].key,
kRainbowModeIndividualKey[i].color));
}
individual_key_rainbow_mode_map_ =
base::flat_map<uint32_t, Color>(std::move(vec));
}
bool RgbKeyboardControllerImpl::IsZonedKeyboard() const {
DCHECK(capabilities_.has_value());
return capabilities_.value() != RgbKeyboardCapabilities::kIndividualKey;
}
void RgbKeyboardControllerImpl::ReinitializeOnDeviceReconnected() {
SetKeyColor({kLeftShiftKey, GetCurrentCapsLockColor(kLeftShiftKey)});
SetKeyColor({kRightShiftKey, GetCurrentCapsLockColor(kRightShiftKey)});
switch (background_type_) {
case BackgroundType::kStaticSingleColor:
SetStaticBackgroundColor(background_color_.r, background_color_.g,
background_color_.b);
break;
case BackgroundType::kStaticRainbow:
SetRainbowMode();
break;
}
}
} // namespace rgbkbd