1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/input/cursor_manager.h"
#include <algorithm>
#include <string>
#include <vector>
#include "base/check.h"
#include "components/input/render_widget_host_view_input.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/gfx/geometry/skia_conversions.h"
namespace input {
CursorManager::CursorManager(RenderWidgetHostViewInput* root)
: view_under_cursor_(root), root_view_(root) {}
CursorManager::~CursorManager() = default;
void CursorManager::UpdateCursor(RenderWidgetHostViewInput* view,
const ui::Cursor& cursor) {
cursor_map_[view] = cursor;
if (view == view_under_cursor_) {
UpdateCursor();
}
}
void CursorManager::UpdateViewUnderCursor(
RenderWidgetHostViewInput* view) {
if (view == view_under_cursor_)
return;
// Whenever we switch from one view to another, clear the tooltip: as the
// mouse moves, the view now controlling the cursor will send a new tooltip,
// though this is only guaranteed if the view's tooltip is non-empty, so
// clearing here is important. Tooltips sent from the previous view will be
// ignored.
root_view_->UpdateTooltip(std::u16string());
view_under_cursor_ = view;
UpdateCursor();
}
void CursorManager::ViewBeingDestroyed(RenderWidgetHostViewInput* view) {
cursor_map_.erase(view);
// If the view right under the mouse is going away, use the root's cursor
// until UpdateViewUnderCursor is called again.
if (view == view_under_cursor_ && view != root_view_)
UpdateViewUnderCursor(root_view_);
}
bool CursorManager::IsViewUnderCursor(
RenderWidgetHostViewInput* view) const {
return view == view_under_cursor_;
}
base::ScopedClosureRunner CursorManager::CreateDisallowCustomCursorScope(
int max_dimension_dips) {
const ui::Cursor& target_cursor = cursor_map_[view_under_cursor_];
const bool cursor_allowed_before = IsCursorAllowed(target_cursor);
dimension_restrictions_.push_back(max_dimension_dips);
// If the new restriction eliminates the cursor under the current view, update
// it.
if (cursor_allowed_before && !IsCursorAllowed(target_cursor)) {
UpdateCursor();
}
return base::ScopedClosureRunner(
base::BindOnce(&CursorManager::DisallowCustomCursorScopeExpired,
weak_factory_.GetWeakPtr(), max_dimension_dips));
}
bool CursorManager::GetCursorForTesting(RenderWidgetHostViewInput* view,
ui::Cursor& cursor) {
if (cursor_map_.find(view) == cursor_map_.end()) {
return false;
}
cursor = cursor_map_[view];
return true;
}
bool CursorManager::IsCursorAllowed(const ui::Cursor& cursor) const {
if (cursor.type() != ui::mojom::CursorType::kCustom ||
dimension_restrictions_.empty()) {
return true;
}
const int max_dimension_dips = std::ranges::min(dimension_restrictions_);
const gfx::Size size_in_dip = gfx::ScaleToCeiledSize(
gfx::SkISizeToSize(cursor.custom_bitmap().dimensions()),
1 / cursor.image_scale_factor());
return std::max(size_in_dip.width(), size_in_dip.height()) <
max_dimension_dips;
}
void CursorManager::DisallowCustomCursorScopeExpired(int max_dimension_dips) {
const ui::Cursor& target_cursor = cursor_map_[view_under_cursor_];
const bool cursor_allowed_before = IsCursorAllowed(target_cursor);
auto it = std::ranges::find(dimension_restrictions_, max_dimension_dips);
CHECK(it != dimension_restrictions_.end());
dimension_restrictions_.erase(it);
if (!cursor_allowed_before && IsCursorAllowed((target_cursor))) {
UpdateCursor();
}
}
void CursorManager::UpdateCursor() {
ui::Cursor cursor(ui::mojom::CursorType::kPointer);
auto it = cursor_map_.find(view_under_cursor_);
if (it != cursor_map_.end() && IsCursorAllowed(it->second)) {
cursor = it->second;
}
last_set_cursor_type_for_testing_ = cursor.type();
root_view_->DisplayCursor(cursor);
}
} // namespace input
|