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