1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/wm/core/cursor_manager.h"
6
7 #include <utility>
8
9 #include "base/check_op.h"
10 #include "base/macros.h"
11 #include "base/trace_event/trace_event.h"
12 #include "ui/aura/client/cursor_client_observer.h"
13 #include "ui/base/cursor/cursor_size.h"
14 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
15 #include "ui/wm/core/native_cursor_manager.h"
16 #include "ui/wm/core/native_cursor_manager_delegate.h"
17
18 namespace wm {
19
20 namespace internal {
21
22 // Represents the cursor state which is composed of cursor type, visibility, and
23 // mouse events enable state. When mouse events are disabled, the cursor is
24 // always invisible.
25 class CursorState {
26 public:
CursorState()27 CursorState()
28 : cursor_(ui::mojom::CursorType::kNone),
29 visible_(true),
30 cursor_size_(ui::CursorSize::kNormal),
31 mouse_events_enabled_(true),
32 visible_on_mouse_events_enabled_(true) {}
33
cursor() const34 gfx::NativeCursor cursor() const { return cursor_; }
set_cursor(gfx::NativeCursor cursor)35 void set_cursor(gfx::NativeCursor cursor) { cursor_ = cursor; }
36
visible() const37 bool visible() const { return visible_; }
SetVisible(bool visible)38 void SetVisible(bool visible) {
39 if (mouse_events_enabled_)
40 visible_ = visible;
41 // Ignores the call when mouse events disabled.
42 }
43
cursor_size() const44 ui::CursorSize cursor_size() const { return cursor_size_; }
set_cursor_size(ui::CursorSize cursor_size)45 void set_cursor_size(ui::CursorSize cursor_size) {
46 cursor_size_ = cursor_size;
47 }
48
mouse_events_enabled() const49 bool mouse_events_enabled() const { return mouse_events_enabled_; }
SetMouseEventsEnabled(bool enabled)50 void SetMouseEventsEnabled(bool enabled) {
51 if (mouse_events_enabled_ == enabled)
52 return;
53 mouse_events_enabled_ = enabled;
54
55 // Restores the visibility when mouse events are enabled.
56 if (enabled) {
57 visible_ = visible_on_mouse_events_enabled_;
58 } else {
59 visible_on_mouse_events_enabled_ = visible_;
60 visible_ = false;
61 }
62 }
63
64 private:
65 gfx::NativeCursor cursor_;
66 bool visible_;
67 ui::CursorSize cursor_size_;
68 bool mouse_events_enabled_;
69
70 // The visibility to set when mouse events are enabled.
71 bool visible_on_mouse_events_enabled_;
72
73 DISALLOW_COPY_AND_ASSIGN(CursorState);
74 };
75
76 } // namespace internal
77
78 bool CursorManager::last_cursor_visibility_state_ = true;
79
CursorManager(std::unique_ptr<NativeCursorManager> delegate)80 CursorManager::CursorManager(std::unique_ptr<NativeCursorManager> delegate)
81 : delegate_(std::move(delegate)),
82 cursor_lock_count_(0),
83 current_state_(new internal::CursorState),
84 state_on_unlock_(new internal::CursorState) {
85 // Restore the last cursor visibility state.
86 current_state_->SetVisible(last_cursor_visibility_state_);
87 }
88
~CursorManager()89 CursorManager::~CursorManager() {
90 }
91
92 // static
ResetCursorVisibilityStateForTest()93 void CursorManager::ResetCursorVisibilityStateForTest() {
94 last_cursor_visibility_state_ = true;
95 }
96
SetCursor(gfx::NativeCursor cursor)97 void CursorManager::SetCursor(gfx::NativeCursor cursor) {
98 SetCursorImpl(cursor, /*forced=*/false);
99 }
100
GetCursor() const101 gfx::NativeCursor CursorManager::GetCursor() const {
102 return current_state_->cursor();
103 }
104
SetCursorForced(gfx::NativeCursor cursor)105 void CursorManager::SetCursorForced(gfx::NativeCursor cursor) {
106 SetCursorImpl(cursor, /*forced=*/true);
107 }
108
ShowCursor()109 void CursorManager::ShowCursor() {
110 last_cursor_visibility_state_ = true;
111 state_on_unlock_->SetVisible(true);
112 if (cursor_lock_count_ == 0 &&
113 IsCursorVisible() != state_on_unlock_->visible()) {
114 delegate_->SetVisibility(state_on_unlock_->visible(), this);
115 if (GetCursor().type() != ui::mojom::CursorType::kNone) {
116 // If the cursor is a visible type, notify the observers.
117 for (auto& observer : observers_)
118 observer.OnCursorVisibilityChanged(true);
119 }
120 }
121 }
122
HideCursor()123 void CursorManager::HideCursor() {
124 last_cursor_visibility_state_ = false;
125 state_on_unlock_->SetVisible(false);
126 if (cursor_lock_count_ == 0 &&
127 IsCursorVisible() != state_on_unlock_->visible()) {
128 delegate_->SetVisibility(state_on_unlock_->visible(), this);
129 for (auto& observer : observers_)
130 observer.OnCursorVisibilityChanged(false);
131 }
132 }
133
IsCursorVisible() const134 bool CursorManager::IsCursorVisible() const {
135 return current_state_->visible();
136 }
137
SetCursorSize(ui::CursorSize cursor_size)138 void CursorManager::SetCursorSize(ui::CursorSize cursor_size) {
139 state_on_unlock_->set_cursor_size(cursor_size);
140 if (GetCursorSize() != state_on_unlock_->cursor_size()) {
141 delegate_->SetCursorSize(state_on_unlock_->cursor_size(), this);
142 for (auto& observer : observers_)
143 observer.OnCursorSizeChanged(cursor_size);
144 }
145 }
146
GetCursorSize() const147 ui::CursorSize CursorManager::GetCursorSize() const {
148 return current_state_->cursor_size();
149 }
150
EnableMouseEvents()151 void CursorManager::EnableMouseEvents() {
152 TRACE_EVENT0("ui,input", "CursorManager::EnableMouseEvents");
153 state_on_unlock_->SetMouseEventsEnabled(true);
154 if (cursor_lock_count_ == 0 &&
155 IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
156 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
157 this);
158 }
159 }
160
DisableMouseEvents()161 void CursorManager::DisableMouseEvents() {
162 TRACE_EVENT0("ui,input", "CursorManager::DisableMouseEvents");
163 state_on_unlock_->SetMouseEventsEnabled(false);
164 if (cursor_lock_count_ == 0 &&
165 IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
166 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
167 this);
168 }
169 }
170
IsMouseEventsEnabled() const171 bool CursorManager::IsMouseEventsEnabled() const {
172 return current_state_->mouse_events_enabled();
173 }
174
SetDisplay(const display::Display & display)175 void CursorManager::SetDisplay(const display::Display& display) {
176 display_ = display;
177 for (auto& observer : observers_)
178 observer.OnCursorDisplayChanged(display);
179
180 delegate_->SetDisplay(display, this);
181 }
182
GetDisplay() const183 const display::Display& CursorManager::GetDisplay() const {
184 return display_;
185 }
186
LockCursor()187 void CursorManager::LockCursor() {
188 cursor_lock_count_++;
189 }
190
UnlockCursor()191 void CursorManager::UnlockCursor() {
192 cursor_lock_count_--;
193 DCHECK_GE(cursor_lock_count_, 0);
194 if (cursor_lock_count_ > 0)
195 return;
196
197 if (GetCursor() != state_on_unlock_->cursor()) {
198 delegate_->SetCursor(state_on_unlock_->cursor(), this);
199 }
200 if (IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
201 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
202 this);
203 }
204 if (IsCursorVisible() != state_on_unlock_->visible()) {
205 delegate_->SetVisibility(state_on_unlock_->visible(),
206 this);
207 }
208 }
209
IsCursorLocked() const210 bool CursorManager::IsCursorLocked() const {
211 return cursor_lock_count_ > 0;
212 }
213
AddObserver(aura::client::CursorClientObserver * observer)214 void CursorManager::AddObserver(
215 aura::client::CursorClientObserver* observer) {
216 observers_.AddObserver(observer);
217 }
218
RemoveObserver(aura::client::CursorClientObserver * observer)219 void CursorManager::RemoveObserver(
220 aura::client::CursorClientObserver* observer) {
221 observers_.RemoveObserver(observer);
222 }
223
ShouldHideCursorOnKeyEvent(const ui::KeyEvent & event) const224 bool CursorManager::ShouldHideCursorOnKeyEvent(
225 const ui::KeyEvent& event) const {
226 return false;
227 }
228
CommitCursor(gfx::NativeCursor cursor)229 void CursorManager::CommitCursor(gfx::NativeCursor cursor) {
230 current_state_->set_cursor(cursor);
231 }
232
CommitVisibility(bool visible)233 void CursorManager::CommitVisibility(bool visible) {
234 // TODO(tdanderson): Find a better place for this so we don't
235 // notify the observers more than is necessary.
236 for (auto& observer : observers_) {
237 observer.OnCursorVisibilityChanged(
238 GetCursor().type() == ui::mojom::CursorType::kNone ? false : visible);
239 }
240 current_state_->SetVisible(visible);
241 }
242
CommitCursorSize(ui::CursorSize cursor_size)243 void CursorManager::CommitCursorSize(ui::CursorSize cursor_size) {
244 current_state_->set_cursor_size(cursor_size);
245 }
246
CommitMouseEventsEnabled(bool enabled)247 void CursorManager::CommitMouseEventsEnabled(bool enabled) {
248 current_state_->SetMouseEventsEnabled(enabled);
249 }
250
SetCursorImpl(gfx::NativeCursor cursor,bool forced)251 void CursorManager::SetCursorImpl(gfx::NativeCursor cursor, bool forced) {
252 bool previously_visible = GetCursor().type() != ui::mojom::CursorType::kNone;
253 state_on_unlock_->set_cursor(cursor);
254 if (cursor_lock_count_ == 0 &&
255 (forced || GetCursor() != state_on_unlock_->cursor())) {
256 delegate_->SetCursor(state_on_unlock_->cursor(), this);
257 bool is_visible = cursor.type() != ui::mojom::CursorType::kNone;
258 if (is_visible != previously_visible) {
259 for (auto& observer : observers_)
260 observer.OnCursorVisibilityChanged(is_visible);
261 }
262 }
263 }
264
265 } // namespace wm
266