blob: e783e00d238932874faa6be0f095112beaaec4e7 [file] [log] [blame]
// 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 "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
namespace content {
CursorManager::CursorManager(RenderWidgetHostViewBase* root)
: view_under_cursor_(root), root_view_(root) {}
CursorManager::~CursorManager() = default;
void CursorManager::UpdateCursor(RenderWidgetHostViewBase* view,
const ui::Cursor& cursor) {
cursor_map_[view] = cursor;
if (view == view_under_cursor_) {
UpdateCursor();
}
}
void CursorManager::UpdateViewUnderCursor(RenderWidgetHostViewBase* 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(RenderWidgetHostViewBase* 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(RenderWidgetHostViewBase* view) const {
return view == view_under_cursor_;
}
base::ScopedClosureRunner CursorManager::CreateDisallowCustomCursorScope() {
bool should_update_cursor = false;
// If custom cursors are about to be disallowed and the current view uses a
// custom cursor, the cursor needs to be updated to replace the custom cursor.
if (AreCustomCursorsAllowed() && cursor_map_[view_under_cursor_].type() ==
ui::mojom::CursorType::kCustom) {
should_update_cursor = true;
}
++disallow_custom_cursor_scope_count_;
if (should_update_cursor) {
UpdateCursor();
}
return base::ScopedClosureRunner(
base::BindOnce(&CursorManager::DisallowCustomCursorScopeExpired,
weak_factory_.GetWeakPtr()));
}
bool CursorManager::GetCursorForTesting(RenderWidgetHostViewBase* view,
ui::Cursor& cursor) {
if (cursor_map_.find(view) == cursor_map_.end()) {
return false;
}
cursor = cursor_map_[view];
return true;
}
bool CursorManager::AreCustomCursorsAllowed() const {
return disallow_custom_cursor_scope_count_ == 0;
}
void CursorManager::DisallowCustomCursorScopeExpired() {
--disallow_custom_cursor_scope_count_;
// If custom cursors started being allowed and the current view has a custom
// cursor, update the cursor to ensure the custom cursor is now displayed.
if (AreCustomCursorsAllowed() && cursor_map_[view_under_cursor_].type() ==
ui::mojom::CursorType::kCustom) {
UpdateCursor();
}
}
void CursorManager::UpdateCursor() {
ui::Cursor cursor(ui::mojom::CursorType::kPointer);
auto it = cursor_map_.find(view_under_cursor_);
if (it != cursor_map_.end() &&
(AreCustomCursorsAllowed() ||
it->second.type() != ui::mojom::CursorType::kCustom)) {
cursor = it->second;
}
last_set_cursor_type_for_testing_ = cursor.type();
root_view_->DisplayCursor(cursor);
}
} // namespace content