Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / ash / wm / workspace / workspace_cycler.cc
blob67319937b6c089718e10cf2bf1488e173ba60d14
1 // Copyright (c) 2012 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.
5 #include "ash/wm/workspace/workspace_cycler.h"
7 #include <cmath>
9 #include "ash/shell.h"
10 #include "ash/wm/workspace/workspace_cycler_configuration.h"
11 #include "ash/wm/workspace/workspace_manager.h"
12 #include "ui/base/events/event.h"
13 #include "ui/base/events/event_utils.h"
15 typedef ash::WorkspaceCyclerConfiguration Config;
17 namespace ash {
18 namespace internal {
20 namespace {
22 // Returns true if cycling is allowed.
23 bool IsCyclingAllowed() {
24 // Cycling is disabled if the screen is locked or a modal dialog is open.
25 return !Shell::GetInstance()->IsScreenLocked() &&
26 !Shell::GetInstance()->IsSystemModalWindowOpen();
29 } // namespace
31 WorkspaceCycler::WorkspaceCycler(WorkspaceManager* workspace_manager)
32 : workspace_manager_(workspace_manager),
33 animator_(NULL),
34 state_(NOT_CYCLING),
35 scroll_x_(0.0f),
36 scroll_y_(0.0f) {
37 ash::Shell::GetInstance()->AddPreTargetHandler(this);
40 WorkspaceCycler::~WorkspaceCycler() {
41 SetState(NOT_CYCLING);
42 ash::Shell::GetInstance()->RemovePreTargetHandler(this);
45 void WorkspaceCycler::AbortCycling() {
46 SetState(NOT_CYCLING);
49 void WorkspaceCycler::SetState(State new_state) {
50 if (state_ == NOT_CYCLING_TRACKING_SCROLL && new_state == STOPPING_CYCLING)
51 new_state = NOT_CYCLING;
53 if (state_ == new_state || !IsValidNextState(new_state))
54 return;
56 state_ = new_state;
58 if (new_state == STARTING_CYCLING) {
59 animator_.reset(new WorkspaceCyclerAnimator(this));
60 workspace_manager_->InitWorkspaceCyclerAnimatorWithCurrentState(
61 animator_.get());
62 animator_->AnimateStartingCycler();
63 } else if (new_state == STOPPING_CYCLING) {
64 if (animator_.get())
65 animator_->AnimateStoppingCycler();
66 } else if (new_state == NOT_CYCLING) {
67 scroll_x_ = 0.0f;
68 scroll_y_ = 0.0f;
69 if (animator_.get()) {
70 animator_->AbortAnimations();
71 animator_.reset();
76 bool WorkspaceCycler::IsValidNextState(State next_state) const {
77 if (state_ == next_state)
78 return true;
80 switch (next_state) {
81 case NOT_CYCLING:
82 return true;
83 case NOT_CYCLING_TRACKING_SCROLL:
84 return state_ == NOT_CYCLING;
85 case STARTING_CYCLING:
86 return state_ == NOT_CYCLING_TRACKING_SCROLL;
87 case CYCLING:
88 return state_ == STARTING_CYCLING;
89 case STOPPING_CYCLING:
90 return (state_ == STARTING_CYCLING || state_ == CYCLING);
93 NOTREACHED();
94 return false;
97 void WorkspaceCycler::OnEvent(ui::Event* event) {
98 if (!IsCyclingAllowed())
99 SetState(NOT_CYCLING);
101 if (state_ != NOT_CYCLING) {
102 if (event->type() == ui::ET_SCROLL_FLING_START ||
103 event->type() == ui::ET_MOUSE_PRESSED ||
104 event->type() == ui::ET_MOUSE_RELEASED ||
105 event->IsKeyEvent()) {
106 SetState(STOPPING_CYCLING);
107 event->StopPropagation();
108 return;
111 ui::EventHandler::OnEvent(event);
114 void WorkspaceCycler::OnScrollEvent(ui::ScrollEvent* event) {
115 if (event->finger_count() != 3 ||
116 event->type() != ui::ET_SCROLL) {
117 if (state_ != NOT_CYCLING)
118 event->StopPropagation();
119 return;
122 if (!IsCyclingAllowed() ||
123 !workspace_manager_->CanStartCyclingThroughWorkspaces()) {
124 DCHECK_EQ(NOT_CYCLING, state_);
125 return;
128 if (state_ == NOT_CYCLING)
129 SetState(NOT_CYCLING_TRACKING_SCROLL);
131 if (ui::IsNaturalScrollEnabled()) {
132 scroll_x_ += event->x_offset_ordinal();
133 scroll_y_ += event->y_offset_ordinal();
134 } else {
135 scroll_x_ -= event->x_offset_ordinal();
136 scroll_y_ -= event->y_offset_ordinal();
139 if (state_ == NOT_CYCLING_TRACKING_SCROLL) {
140 double distance_to_initiate_cycling = Config::GetDouble(
141 Config::DISTANCE_TO_INITIATE_CYCLING);
143 if (fabs(scroll_x_) > distance_to_initiate_cycling) {
144 // Only initiate workspace cycling if there recently was a significant
145 // amount of vertical movement as opposed to vertical movement
146 // accumulated over a long horizontal three finger scroll.
147 scroll_x_ = 0.0f;
148 scroll_y_ = 0.0f;
151 if (fabs(scroll_y_) >= distance_to_initiate_cycling)
152 SetState(STARTING_CYCLING);
155 if (state_ == CYCLING && event->y_offset_ordinal() != 0.0f) {
156 DCHECK(animator_.get());
157 animator_->AnimateCyclingByScrollDelta(event->y_offset_ordinal());
158 event->SetHandled();
162 void WorkspaceCycler::StartWorkspaceCyclerAnimationFinished() {
163 DCHECK_EQ(STARTING_CYCLING, state_);
164 SetState(CYCLING);
167 void WorkspaceCycler::StopWorkspaceCyclerAnimationFinished() {
168 DCHECK_EQ(STOPPING_CYCLING, state_);
169 Workspace* workspace_to_activate = animator_->get_selected_workspace();
170 animator_.reset();
171 SetState(NOT_CYCLING);
173 // Activate the workspace after updating the state so that a call to
174 // AbortCycling() as a result of SetActiveWorkspaceFromCycler() is a noop.
175 workspace_manager_->SetActiveWorkspaceFromCycler(workspace_to_activate);
178 } // namespace internal
179 } // namespace ash