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/views/corewm/cursor_manager.h"
6
7 #include "base/logging.h"
8 #include "ui/aura/client/cursor_client_observer.h"
9 #include "ui/views/corewm/native_cursor_manager.h"
10 #include "ui/views/corewm/native_cursor_manager_delegate.h"
11
12 namespace views {
13 namespace corewm {
14
15 namespace internal {
16
17 // Represents the cursor state which is composed of cursor type, visibility, and
18 // mouse events enable state. When mouse events are disabled, the cursor is
19 // always invisible.
20 class CursorState {
21 public:
CursorState()22 CursorState()
23 : cursor_(ui::kCursorNone),
24 visible_(true),
25 scale_(1.f),
26 cursor_set_(ui::CURSOR_SET_NORMAL),
27 mouse_events_enabled_(true),
28 visible_on_mouse_events_enabled_(true) {
29 }
30
cursor() const31 gfx::NativeCursor cursor() const { return cursor_; }
set_cursor(gfx::NativeCursor cursor)32 void set_cursor(gfx::NativeCursor cursor) { cursor_ = cursor; }
33
visible() const34 bool visible() const { return visible_; }
SetVisible(bool visible)35 void SetVisible(bool visible) {
36 if (mouse_events_enabled_)
37 visible_ = visible;
38 // Ignores the call when mouse events disabled.
39 }
40
scale() const41 float scale() const { return scale_; }
set_scale(float scale)42 void set_scale(float scale) {
43 scale_ = scale;
44 }
45
cursor_set() const46 ui::CursorSetType cursor_set() const { return cursor_set_; }
set_cursor_set(ui::CursorSetType cursor_set)47 void set_cursor_set(ui::CursorSetType cursor_set) {
48 cursor_set_ = cursor_set;
49 }
50
mouse_events_enabled() const51 bool mouse_events_enabled() const { return mouse_events_enabled_; }
SetMouseEventsEnabled(bool enabled)52 void SetMouseEventsEnabled(bool enabled) {
53 if (mouse_events_enabled_ == enabled)
54 return;
55 mouse_events_enabled_ = enabled;
56
57 // Restores the visibility when mouse events are enabled.
58 if (enabled) {
59 visible_ = visible_on_mouse_events_enabled_;
60 } else {
61 visible_on_mouse_events_enabled_ = visible_;
62 visible_ = false;
63 }
64 }
65
66 private:
67 gfx::NativeCursor cursor_;
68 bool visible_;
69 float scale_;
70 ui::CursorSetType cursor_set_;
71 bool mouse_events_enabled_;
72
73 // The visibility to set when mouse events are enabled.
74 bool visible_on_mouse_events_enabled_;
75
76 DISALLOW_COPY_AND_ASSIGN(CursorState);
77 };
78
79 } // namespace internal
80
CursorManager(scoped_ptr<NativeCursorManager> delegate)81 CursorManager::CursorManager(scoped_ptr<NativeCursorManager> delegate)
82 : delegate_(delegate.Pass()),
83 cursor_lock_count_(0),
84 current_state_(new internal::CursorState),
85 state_on_unlock_(new internal::CursorState) {
86 }
87
~CursorManager()88 CursorManager::~CursorManager() {
89 }
90
SetCursor(gfx::NativeCursor cursor)91 void CursorManager::SetCursor(gfx::NativeCursor cursor) {
92 state_on_unlock_->set_cursor(cursor);
93 if (cursor_lock_count_ == 0 &&
94 GetCursor() != state_on_unlock_->cursor()) {
95 delegate_->SetCursor(state_on_unlock_->cursor(), this);
96 }
97 }
98
GetCursor() const99 gfx::NativeCursor CursorManager::GetCursor() const {
100 return current_state_->cursor();
101 }
102
ShowCursor()103 void CursorManager::ShowCursor() {
104 state_on_unlock_->SetVisible(true);
105 if (cursor_lock_count_ == 0 &&
106 IsCursorVisible() != state_on_unlock_->visible()) {
107 delegate_->SetVisibility(state_on_unlock_->visible(), this);
108 FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
109 OnCursorVisibilityChanged(true));
110 }
111 }
112
HideCursor()113 void CursorManager::HideCursor() {
114 state_on_unlock_->SetVisible(false);
115 if (cursor_lock_count_ == 0 &&
116 IsCursorVisible() != state_on_unlock_->visible()) {
117 delegate_->SetVisibility(state_on_unlock_->visible(), this);
118 FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
119 OnCursorVisibilityChanged(false));
120 }
121 }
122
IsCursorVisible() const123 bool CursorManager::IsCursorVisible() const {
124 return current_state_->visible();
125 }
126
SetScale(float scale)127 void CursorManager::SetScale(float scale) {
128 state_on_unlock_->set_scale(scale);
129 if (GetScale() != state_on_unlock_->scale())
130 delegate_->SetScale(state_on_unlock_->scale(), this);
131 }
132
GetScale() const133 float CursorManager::GetScale() const {
134 return current_state_->scale();
135 }
136
SetCursorSet(ui::CursorSetType cursor_set)137 void CursorManager::SetCursorSet(ui::CursorSetType cursor_set) {
138 state_on_unlock_->set_cursor_set(cursor_set);
139 if (GetCursorSet() != state_on_unlock_->cursor_set())
140 delegate_->SetCursorSet(state_on_unlock_->cursor_set(), this);
141 }
142
GetCursorSet() const143 ui::CursorSetType CursorManager::GetCursorSet() const {
144 return current_state_->cursor_set();
145 }
146
EnableMouseEvents()147 void CursorManager::EnableMouseEvents() {
148 state_on_unlock_->SetMouseEventsEnabled(true);
149 if (cursor_lock_count_ == 0 &&
150 IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
151 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
152 this);
153 }
154 }
155
DisableMouseEvents()156 void CursorManager::DisableMouseEvents() {
157 state_on_unlock_->SetMouseEventsEnabled(false);
158 if (cursor_lock_count_ == 0 &&
159 IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
160 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
161 this);
162 }
163 }
164
IsMouseEventsEnabled() const165 bool CursorManager::IsMouseEventsEnabled() const {
166 return current_state_->mouse_events_enabled();
167 }
168
SetDisplay(const gfx::Display & display)169 void CursorManager::SetDisplay(const gfx::Display& display) {
170 delegate_->SetDisplay(display, this);
171 }
172
LockCursor()173 void CursorManager::LockCursor() {
174 cursor_lock_count_++;
175 }
176
UnlockCursor()177 void CursorManager::UnlockCursor() {
178 cursor_lock_count_--;
179 DCHECK_GE(cursor_lock_count_, 0);
180 if (cursor_lock_count_ > 0)
181 return;
182
183 if (GetCursor() != state_on_unlock_->cursor()) {
184 delegate_->SetCursor(state_on_unlock_->cursor(), this);
185 }
186 if (IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
187 delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
188 this);
189 }
190 if (IsCursorVisible() != state_on_unlock_->visible()) {
191 delegate_->SetVisibility(state_on_unlock_->visible(),
192 this);
193 }
194 }
195
IsCursorLocked() const196 bool CursorManager::IsCursorLocked() const {
197 return cursor_lock_count_ > 0;
198 }
199
AddObserver(aura::client::CursorClientObserver * observer)200 void CursorManager::AddObserver(
201 aura::client::CursorClientObserver* observer) {
202 observers_.AddObserver(observer);
203 }
204
RemoveObserver(aura::client::CursorClientObserver * observer)205 void CursorManager::RemoveObserver(
206 aura::client::CursorClientObserver* observer) {
207 observers_.RemoveObserver(observer);
208 }
209
CommitCursor(gfx::NativeCursor cursor)210 void CursorManager::CommitCursor(gfx::NativeCursor cursor) {
211 current_state_->set_cursor(cursor);
212 }
213
CommitVisibility(bool visible)214 void CursorManager::CommitVisibility(bool visible) {
215 // TODO(tdanderson): Find a better place for this so we don't
216 // notify the observers more than is necessary.
217 FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
218 OnCursorVisibilityChanged(visible));
219 current_state_->SetVisible(visible);
220 }
221
CommitScale(float scale)222 void CursorManager::CommitScale(float scale) {
223 current_state_->set_scale(scale);
224 }
225
CommitCursorSet(ui::CursorSetType cursor_set)226 void CursorManager::CommitCursorSet(ui::CursorSetType cursor_set) {
227 current_state_->set_cursor_set(cursor_set);
228 }
229
CommitMouseEventsEnabled(bool enabled)230 void CursorManager::CommitMouseEventsEnabled(bool enabled) {
231 current_state_->SetMouseEventsEnabled(enabled);
232 }
233
234 } // namespace corewm
235 } // namespace views
236