blob: 6b6d050ca30f14c0d0bee4eda5ab8a5b334305d0 [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 "chrome/browser/ash/arc/input_overlay/ui/ui_utils.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ash/arc/input_overlay/constants.h"
#include "chromeos/strings/grit/chromeos_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace arc::input_overlay {
namespace {
// Arrow symbols for arrow keys.
constexpr char16_t kLeftArrow[] = u"←";
constexpr char16_t kUpArrow[] = u"↑";
constexpr char16_t kRightArrow[] = u"→";
constexpr char16_t kDownArrow[] = u"↓";
constexpr char16_t kBackQuote[] = u"`";
constexpr char16_t kMinus[] = u"-";
constexpr char16_t kEqual[] = u"=";
constexpr char16_t kBracketLeft[] = u"[";
constexpr char16_t kBracketRight[] = u"]";
constexpr char16_t kBackSlash[] = u"\\";
constexpr char16_t kSemicolon[] = u";";
constexpr char16_t kQuote[] = u"'";
constexpr char16_t kComma[] = u",";
constexpr char16_t kPeriod[] = u".";
constexpr char16_t kSlash[] = u"/";
constexpr char16_t kBackSpace[] = u"⌫";
constexpr char16_t kEnter[] = u"↵";
constexpr char16_t kSpace[] = u"␣";
constexpr char16_t kEscape[] = u"esc";
// Modifier keys.
constexpr char16_t kAlt[] = u"alt";
constexpr char16_t kCtrl[] = u"ctrl";
constexpr char16_t kShift[] = u"shift";
constexpr char16_t kCap[] = u"cap";
} // namespace
std::u16string GetDisplayText(const ui::DomCode code) {
switch (code) {
case ui::DomCode::NONE:
return kUnknownBind;
case ui::DomCode::ARROW_LEFT:
return kLeftArrow;
case ui::DomCode::ARROW_RIGHT:
return kRightArrow;
case ui::DomCode::ARROW_UP:
return kUpArrow;
case ui::DomCode::ARROW_DOWN:
return kDownArrow;
case ui::DomCode::BACKQUOTE:
return kBackQuote;
case ui::DomCode::MINUS:
return kMinus;
case ui::DomCode::EQUAL:
return kEqual;
case ui::DomCode::BRACKET_LEFT:
return kBracketLeft;
case ui::DomCode::BRACKET_RIGHT:
return kBracketRight;
case ui::DomCode::BACKSLASH:
return kBackSlash;
case ui::DomCode::SEMICOLON:
return kSemicolon;
case ui::DomCode::QUOTE:
return kQuote;
case ui::DomCode::COMMA:
return kComma;
case ui::DomCode::PERIOD:
return kPeriod;
case ui::DomCode::SLASH:
return kSlash;
case ui::DomCode::BACKSPACE:
return kBackSpace;
case ui::DomCode::ENTER:
return kEnter;
case ui::DomCode::ESCAPE:
return kEscape;
// Modifier keys.
case ui::DomCode::ALT_LEFT:
case ui::DomCode::ALT_RIGHT:
return kAlt;
case ui::DomCode::CONTROL_LEFT:
case ui::DomCode::CONTROL_RIGHT:
return kCtrl;
case ui::DomCode::SHIFT_LEFT:
case ui::DomCode::SHIFT_RIGHT:
return kShift;
case ui::DomCode::CAPS_LOCK:
return kCap;
case ui::DomCode::SPACE:
return kSpace;
default:
std::string dom_code_string =
ui::KeycodeConverter::DomCodeToCodeString(code);
if (base::StartsWith(dom_code_string, "Key",
base::CompareCase::SENSITIVE)) {
return base::UTF8ToUTF16(base::ToLowerASCII(dom_code_string.substr(3)));
}
if (base::StartsWith(dom_code_string, "Digit",
base::CompareCase::SENSITIVE)) {
return base::UTF8ToUTF16(dom_code_string.substr(5));
}
// TODO(b/282843422): better display for number pad. Current it shows in
// the format of "numpad1" since the number keys on number pad are not
// considered the same as numbers on the main keyboard.
auto lower = base::ToLowerASCII(dom_code_string);
return base::UTF8ToUTF16(lower);
}
}
std::u16string GetDisplayTextAccessibleName(const std::u16string& text) {
if (text.compare(kSpace) == 0) {
return l10n_util::GetStringUTF16(IDS_INPUT_OVERLAY_KEY_LABEL_SPACE);
} else if (text.compare(kEnter) == 0) {
return l10n_util::GetStringUTF16(IDS_INPUT_OVERLAY_KEY_LABEL_ENTER);
} else if (text.compare(kBackSpace) == 0) {
return l10n_util::GetStringUTF16(IDS_INPUT_OVERLAY_KEY_LABEL_BACKSPACE);
} else {
return text;
}
}
gfx::Rect CalculateAvailableBounds(aura::Window* root_window) {
DCHECK(root_window->IsRootWindow());
const auto* shelf =
ash::RootWindowController::ForWindow(root_window)->shelf();
DCHECK(shelf);
if (!shelf->IsVisible()) {
return root_window->bounds();
}
int x = 0, y = 0;
int width = root_window->bounds().width();
int height = root_window->bounds().height();
const int shelf_size = ash::ShelfConfig::Get()->shelf_size();
if (shelf->alignment() == ash::ShelfAlignment::kLeft) {
x += shelf_size;
width -= shelf_size;
} else if (shelf->alignment() == ash::ShelfAlignment::kRight) {
width -= shelf_size;
} else {
// Include `kBottom` and `kBottomLocked`. Shelf has no alignment on top.
height -= shelf_size;
}
return gfx::Rect(x, y, width, height);
}
SkAlpha GetAlpha(float opacity_percent) {
return base::saturated_cast<SkAlpha>(std::numeric_limits<SkAlpha>::max() *
opacity_percent);
}
bool OffsetPositionByArrowKey(ui::KeyboardCode key, gfx::Point& position) {
switch (key) {
case ui::VKEY_LEFT:
position.Offset(-kArrowKeyMoveDistance, 0);
break;
case ui::VKEY_RIGHT:
position.Offset(kArrowKeyMoveDistance, 0);
break;
case ui::VKEY_UP:
position.Offset(0, -kArrowKeyMoveDistance);
break;
case ui::VKEY_DOWN:
position.Offset(0, kArrowKeyMoveDistance);
break;
default:
return false;
}
return true;
}
} // namespace arc::input_overlay