blob: 51440a96a21daac3bc87adb46e4e060d4cf19961 [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/utility/cursor_setter.h"
#include "ash/display/screen_orientation_controller.h"
#include "ash/shell.h"
namespace ash {
CursorSetter::CursorSetter()
: cursor_manager_(Shell::Get()->cursor_manager()),
original_cursor_(cursor_manager_->GetCursor()),
original_cursor_visible_(cursor_manager_->IsCursorVisible()),
original_cursor_locked_(cursor_manager_->IsCursorLocked()) {
if (!cursor_manager_->IsMouseEventsEnabled()) {
cursor_manager_->EnableMouseEvents();
}
}
CursorSetter::~CursorSetter() {
custom_cursor_params_.reset();
ResetCursor();
}
void CursorSetter::UpdateCursor(aura::Window* root_window,
const ui::Cursor& cursor,
std::optional<int> custom_type_id) {
if (original_cursor_locked_) {
return;
}
if (in_cursor_update_) {
return;
}
base::AutoReset<bool> auto_reset_in_cursor_update(&in_cursor_update_, true);
const ui::mojom::CursorType new_cursor_type = cursor.type();
const float device_scale_factor = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_window)
.device_scale_factor();
const chromeos::OrientationType orientation = GetCurrentScreenOrientation();
if (!DidCursorChange(new_cursor_type, device_scale_factor, orientation,
custom_type_id)) {
return;
}
if (new_cursor_type == ui::mojom::CursorType::kCustom) {
custom_cursor_params_ = CustomCursorParams{
custom_type_id.value(), device_scale_factor, orientation};
}
if (cursor_manager_->IsCursorLocked()) {
cursor_manager_->UnlockCursor();
}
if (new_cursor_type == ui::mojom::CursorType::kNone) {
cursor_manager_->HideCursor();
} else {
cursor_manager_->SetCursor(cursor);
cursor_manager_->ShowCursor();
}
cursor_manager_->LockCursor();
was_cursor_reset_to_original_ = false;
}
void CursorSetter::HideCursor() {
if (original_cursor_locked_ || !IsCursorVisible()) {
return;
}
if (cursor_manager_->IsCursorLocked()) {
cursor_manager_->UnlockCursor();
}
cursor_manager_->HideCursor();
cursor_manager_->LockCursor();
was_cursor_reset_to_original_ = false;
}
void CursorSetter::ResetCursor() {
// Only unlock the cursor if it wasn't locked before.
if (original_cursor_locked_) {
return;
}
// Only reset cursor if it hasn't been reset before.
if (was_cursor_reset_to_original_) {
return;
}
if (cursor_manager_->IsCursorLocked()) {
cursor_manager_->UnlockCursor();
}
cursor_manager_->SetCursor(original_cursor_);
if (original_cursor_visible_) {
cursor_manager_->ShowCursor();
} else {
cursor_manager_->HideCursor();
}
was_cursor_reset_to_original_ = true;
}
bool CursorSetter::IsCursorVisible() const {
return cursor_manager_->IsCursorVisible();
}
bool CursorSetter::IsUsingCustomCursor(int custom_type_id) const {
return cursor_manager_->GetCursor().type() ==
ui::mojom::CursorType::kCustom &&
custom_cursor_params_->id == custom_type_id;
}
bool CursorSetter::DidCursorChange(
ui::mojom::CursorType new_cursor_type,
float device_scale_factor,
chromeos::OrientationType orientation,
const std::optional<int> custom_type_id) const {
const ui::mojom::CursorType current_cursor_type =
cursor_manager_->GetCursor().type();
if (current_cursor_type != new_cursor_type) {
return true;
}
// We use `kNone` as a signal to hide the cursor. See `UpdateCursor()`.
bool visibility_changed = cursor_manager_->IsCursorVisible() !=
(new_cursor_type != ui::mojom::CursorType::kNone);
if (visibility_changed) {
return true;
}
if (current_cursor_type == ui::mojom::CursorType::kCustom) {
CHECK(custom_type_id);
return (custom_cursor_params_ != CustomCursorParams{custom_type_id.value(),
device_scale_factor,
orientation});
}
return false;
}
} // namespace ash