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