Index: services/ui/ws/display.cc |
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc |
index becd40ed97784b72dbada881f97b3c6838de21e2..1848b4b29ddd5c52d70df9ce7f940ae74ebe391b 100644 |
--- a/services/ui/ws/display.cc |
+++ b/services/ui/ws/display.cc |
@@ -36,9 +36,42 @@ |
namespace ui { |
namespace ws { |
+class Display::CursorState { |
+ public: |
+ CursorState() |
+ : cursor_data_(ui::CursorData(ui::CursorType::kNull)), visible_(true) {} |
+ CursorState(const CursorState& rhs) = default; |
+ ~CursorState() {} |
+ |
+ const base::Optional<ui::CursorData>& global_override_cursor() const { |
+ return global_override_cursor_; |
+ } |
+ void SetGlobalOverrideCursor(const base::Optional<ui::CursorData>& cursor) { |
+ global_override_cursor_ = cursor; |
+ } |
+ |
+ const ui::CursorData& cursor_data() const { return cursor_data_; } |
+ void SetCursorData(const ui::CursorData& data) { cursor_data_ = data; } |
+ |
+ bool visible() const { return visible_; } |
+ void set_visible(bool visible) { visible_ = visible; } |
+ |
+ private: |
+ // An optional cursor set by the window manager which overrides per-window |
+ // requests. |
+ base::Optional<ui::CursorData> global_override_cursor_; |
+ |
+ // The last cursor set. Used to track whether we need to change the cursor. |
+ ui::CursorData cursor_data_; |
+ |
+ // Whether the cursor is visible. |
+ bool visible_; |
+}; |
+ |
Display::Display(WindowServer* window_server) |
: window_server_(window_server), |
- last_cursor_(ui::CursorData(ui::CursorType::kNull)) { |
+ current_state_(base::MakeUnique<CursorState>()), |
+ state_on_unlock_(base::MakeUnique<CursorState>()) { |
window_server_->window_manager_window_tree_factory_set()->AddObserver(this); |
window_server_->user_id_tracker()->AddObserver(this); |
} |
@@ -199,9 +232,54 @@ void Display::RemoveWindowManagerDisplayRoot( |
} |
void Display::UpdateNativeCursor(const ui::CursorData& cursor) { |
- if (!last_cursor_.IsSameAs(cursor)) { |
- platform_display_->SetCursor(cursor); |
- last_cursor_ = cursor; |
+ if (!state_on_unlock_->cursor_data().IsSameAs(cursor)) |
+ state_on_unlock_->SetCursorData(cursor); |
+ |
+ if (cursor_lock_count_ == 0 && |
+ !current_state_->cursor_data().IsSameAs(cursor)) { |
+ current_state_->SetCursorData(cursor); |
+ SetPlatformCursor(); |
+ } |
+} |
+ |
+void Display::LockCursor() { |
+ cursor_lock_count_++; |
+} |
+ |
+void Display::UnlockCursor() { |
+ cursor_lock_count_--; |
sky
2017/05/12 13:40:01
Having each Display track this state is rather dup
Elliot Glaysher
2017/05/12 23:02:44
Created CursorState class, which is owned by windo
|
+ DCHECK_GE(cursor_lock_count_, 0); |
+ if (cursor_lock_count_ > 0) |
+ return; |
+ |
+ *current_state_ = *state_on_unlock_; |
+ SetPlatformCursor(); |
+} |
+ |
+void Display::ShowCursor() { |
+ state_on_unlock_->set_visible(true); |
+ if (cursor_lock_count_ == 0 && |
+ current_state_->visible() != state_on_unlock_->visible()) { |
+ current_state_->set_visible(true); |
+ SetPlatformCursor(); |
+ } |
+} |
+ |
+void Display::HideCursor() { |
+ state_on_unlock_->set_visible(false); |
+ if (cursor_lock_count_ == 0 && |
+ current_state_->visible() != state_on_unlock_->visible()) { |
+ platform_display_->SetCursor(ui::CursorData(ui::CursorType::kNone)); |
+ current_state_->set_visible(false); |
+ } |
+} |
+ |
+void Display::SetGlobalOverrideCursor( |
+ const base::Optional<ui::CursorData>& cursor) { |
+ state_on_unlock_->SetGlobalOverrideCursor(cursor); |
+ if (cursor_lock_count_ == 0) { |
+ current_state_->SetGlobalOverrideCursor(cursor); |
+ SetPlatformCursor(); |
} |
} |
@@ -273,6 +351,19 @@ void Display::CreateRootWindow(const gfx::Size& size) { |
focus_controller_->AddObserver(this); |
} |
+void Display::SetPlatformCursor() { |
+ if (current_state_->visible()) { |
+ if (current_state_->global_override_cursor().has_value()) { |
+ platform_display_->SetCursor( |
+ current_state_->global_override_cursor().value()); |
+ } else { |
+ platform_display_->SetCursor(current_state_->cursor_data()); |
+ } |
+ } else { |
+ platform_display_->SetCursor(ui::CursorData(ui::CursorType::kNone)); |
+ } |
+} |
+ |
ServerWindow* Display::GetRootWindow() { |
return root_.get(); |
} |