diff --git a/ash/ash.gyp b/ash/ash.gyp index dabdfb540d9c29..5f34493802f1bc 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -432,6 +432,8 @@ 'wm/workspace/workspace_cycler.h', 'wm/workspace/workspace_cycler_animator.cc', 'wm/workspace/workspace_cycler_animator.h', + 'wm/workspace/workspace_cycler_configuration.cc', + 'wm/workspace/workspace_cycler_configuration.h', 'wm/workspace/workspace_event_handler.cc', 'wm/workspace/workspace_event_handler.h', 'wm/workspace/workspace_layout_manager.cc', diff --git a/ash/wm/workspace/workspace_cycler.cc b/ash/wm/workspace/workspace_cycler.cc index 5015fff092d275..d7e7d6b7294726 100644 --- a/ash/wm/workspace/workspace_cycler.cc +++ b/ash/wm/workspace/workspace_cycler.cc @@ -7,18 +7,18 @@ #include #include "ash/shell.h" +#include "ash/wm/workspace/workspace_cycler_configuration.h" #include "ash/wm/workspace/workspace_manager.h" #include "ui/base/events/event.h" #include "ui/base/events/event_utils.h" +typedef ash::WorkspaceCyclerConfiguration Config; + namespace ash { namespace internal { namespace { -// The required vertical distance to initiate workspace cycling. -const float kDistanceToInitiateWorkspaceCycling = 10.0f; - // Returns true if cycling is allowed. bool IsCyclingAllowed() { // Cycling is disabled if the screen is locked or a modal dialog is open. @@ -133,7 +133,10 @@ void WorkspaceCycler::OnScrollEvent(ui::ScrollEvent* event) { } if (state_ == NOT_CYCLING_TRACKING_SCROLL) { - if (fabs(scroll_x_) > kDistanceToInitiateWorkspaceCycling) { + double distance_to_initiate_cycling = Config::GetDouble( + Config::DISTANCE_TO_INITIATE_CYCLING); + + if (fabs(scroll_x_) > distance_to_initiate_cycling) { // Only initiate workspace cycling if there recently was a significant // amount of vertical movement as opposed to vertical movement // accumulated over a long horizontal three finger scroll. @@ -141,7 +144,7 @@ void WorkspaceCycler::OnScrollEvent(ui::ScrollEvent* event) { scroll_y_ = 0.0f; } - if (fabs(scroll_y_) >= kDistanceToInitiateWorkspaceCycling) + if (fabs(scroll_y_) >= distance_to_initiate_cycling) SetState(STARTING_CYCLING); } diff --git a/ash/wm/workspace/workspace_cycler_animator.cc b/ash/wm/workspace/workspace_cycler_animator.cc index a10bf944cff24b..ce7ecf3a422082 100644 --- a/ash/wm/workspace/workspace_cycler_animator.cc +++ b/ash/wm/workspace/workspace_cycler_animator.cc @@ -15,6 +15,8 @@ #include "ash/wm/shelf_layout_manager.h" #include "ash/wm/workspace/colored_window_controller.h" #include "ash/wm/workspace/workspace.h" +#include "ash/wm/workspace/workspace_cycler_configuration.h" +#include "base/values.h" #include "ui/aura/window.h" #include "ui/base/events/event_utils.h" #include "ui/compositor/layer_animator.h" @@ -22,49 +24,7 @@ #include "ui/gfx/transform_util.h" #include "ui/views/widget/widget.h" -namespace { - -// The maximum number of visible workspaces deeper than the selected workspace. -const int kMinVisibleOffsetFromSelected = -2; - -// The maximum number of visible workspaces shallower than the selected -// workspace. -const int kMaxVisibleOffsetFromSelected = 3; - -// The scale of the selected workspace when it is completely selected. -const double kSelectedWorkspaceScale = 0.95; - -// The minimum scale for workspaces in the top stack. The scales of the -// workspaces in the top stack decrease as you go deeper into the stack. -const double kMinTopStackScale = 0.9; - -// The maximum scale for workspaces in the bottom stack. The scales of the -// workspaces in the bottom stack increase as you go up the stack. -const double kMaxBottomStackScale = 1.0; - -// The minimum workspace brightness. -const float kMinBrightness = -0.4f; - -// The required vertical scroll amount to cycle to the next / previous -// workspace. -const double kScrollAmountToCycleToNextWorkspace = 10; - -// The ratio of the duration of the animation to the amount that the user has -// scrolled. -// The duration of an animation is computed by: -// distance scrolled * |kCyclerStepAnimationDurationRatio|. -const double kCyclerStepAnimationDurationRatio = 10; - -// The duration of the animations when animating starting the cycler. -const int kStartCyclerAnimationDuration = 100; - -// The duration of the animations when animating stopping the cycler. -const int kStopCyclerAnimationDuration = 100; - -// The background opacity. -const float kBackgroundOpacity = .8f; - -} // namespace +typedef ash::WorkspaceCyclerConfiguration Config; namespace ash { namespace internal { @@ -130,6 +90,16 @@ class StyleCalculator { bool GetTargetVisibilityForOffset(int offset_from_selected, size_t workspace_index) const; + // Returns the minimum offset from the selected workspace at which a + // workspace can be visible. The offset is used to limit the amount of + // workspaces which are simultaneously visible. + int GetMinVisibleOffsetFromSelected() const; + + // Returns the maximum offset from the selected workspace at which a + // workspace can be visible. The offset is used to limit the amount of + // workspaces which are simultaneously visible. + int GetMaxVisibleOffsetFromSelected() const; + // The bounds of the display containing the workspaces in workspace // coordinates, including the shelf if any. const gfx::Rect screen_bounds_; @@ -201,7 +171,10 @@ void StyleCalculator::GetTargetProperties( second_offset_from_selected = offset_from_selected - 1; } - double progress = fabs(scroll_delta / kScrollAmountToCycleToNextWorkspace); + double scroll_distance_to_cycle_to_next_workspace = Config::GetDouble( + Config::SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE); + double progress = fabs( + scroll_delta / scroll_distance_to_cycle_to_next_workspace); DCHECK_GT(1.0, progress); if (transform) { @@ -251,9 +224,11 @@ gfx::Transform StyleCalculator::GetStoppedTargetTransformForOffset( // The workspaces shallower than the selected workspace are stacked exactly // on top of each other offscreen. + double max_scale = Config::GetDouble(Config::MAX_SCALE); + gfx::Transform transform; transform.Translate(0, screen_bounds_.height()); - transform.Scale(kMaxBottomStackScale, kMaxBottomStackScale); + transform.Scale(max_scale, max_scale); return transform; } @@ -282,41 +257,50 @@ gfx::DecomposedTransform StyleCalculator::GetTargetTransformForOffset( // which will be activated if the user does not do any more cycling. bool in_top_stack = (offset_from_selected <= 0); - // Give workspaces with offsets below |kMinVisibleOffsetFromSelected| the - // same transform as the workspace at |kMinVisibleOffsetFromSelected|. As - // the workspace at |kMinVisibleOffsetFromSelected| completely occludes - // these extra workspaces, they can be hidden. - // |kMaxVisibleOffsetFromSelected| is dealt with similarly. - if (offset_from_selected < kMinVisibleOffsetFromSelected) - offset_from_selected = kMinVisibleOffsetFromSelected; - else if (offset_from_selected > kMaxVisibleOffsetFromSelected) - offset_from_selected = kMaxVisibleOffsetFromSelected; - - double scale = kSelectedWorkspaceScale; + int min_visible_offset_from_selected = GetMinVisibleOffsetFromSelected(); + int max_visible_offset_from_selected = GetMaxVisibleOffsetFromSelected(); + + // Give workspaces at hidden offsets the transform of the workspace at the + // nearest visible offset. This is needed to produce a valid result when + // interpolating between the values of GetTargetTransformForOffset() for a + // visible and hidden offset. + if (offset_from_selected < min_visible_offset_from_selected) + offset_from_selected = min_visible_offset_from_selected; + else if (offset_from_selected > max_visible_offset_from_selected) + offset_from_selected = max_visible_offset_from_selected; + + double selected_scale = Config::GetDouble(Config::SELECTED_SCALE); + + double scale = selected_scale; if (in_top_stack) { + double min_scale = Config::GetDouble(Config::MIN_SCALE); scale -= static_cast(offset_from_selected) / - kMinVisibleOffsetFromSelected * - (kSelectedWorkspaceScale - kMinTopStackScale); + min_visible_offset_from_selected * (selected_scale - min_scale); } else { + double max_scale = Config::GetDouble(Config::MAX_SCALE); scale += static_cast(offset_from_selected) / - kMaxVisibleOffsetFromSelected * - (kMaxBottomStackScale - kSelectedWorkspaceScale); + max_visible_offset_from_selected * (max_scale - selected_scale); } - // Compute the workspace's y offset. As abs(|offset_from_selected|) increases, - // the amount of the top of the workspace which is visible from beneath the - // shallower workspaces decreases exponentially. + // Compute the workspace's y offset. double y_offset = 0; - if (in_top_stack) { - const double kTopStackYOffsets[-kMinVisibleOffsetFromSelected + 1] = - { 40, 28, 20 }; - y_offset = kTopStackYOffsets[ - static_cast(std::abs(offset_from_selected))]; + if (offset_from_selected == 0) { + y_offset = Config::GetDouble(Config::SELECTED_Y_OFFSET); } else { - const double kBottomStackYOffsets[kMaxVisibleOffsetFromSelected] = - { -40, -32, -20 }; - y_offset = maximized_bounds_.height() + - kBottomStackYOffsets[static_cast(offset_from_selected - 1)]; + Config::Property y_offsets_property; + if (in_top_stack) { + y_offsets_property = Config::DEEPER_THAN_SELECTED_Y_OFFSETS; + } else { + y_offsets_property = Config::SHALLOWER_THAN_SELECTED_Y_OFFSETS; + y_offset = maximized_bounds_.height(); + } + const base::ListValue& y_offsets = Config::GetListValue(y_offsets_property); + size_t y_offset_index = static_cast( + std::abs(offset_from_selected) - 1); + DCHECK_GT(y_offsets.GetSize(), y_offset_index); + double y_offset_config_value = 0; + y_offsets.GetDouble(y_offset_index, &y_offset_config_value); + y_offset += y_offset_config_value; } // Center the workspace horizontally. @@ -333,8 +317,9 @@ gfx::DecomposedTransform StyleCalculator::GetTargetTransformForOffset( float StyleCalculator::GetTargetBrightnessForOffset( int offset_from_selected) const { int max_visible_distance_from_selected = std::max( - std::abs(kMinVisibleOffsetFromSelected), kMaxVisibleOffsetFromSelected); - return kMinBrightness * std::min( + std::abs(GetMinVisibleOffsetFromSelected()), + GetMaxVisibleOffsetFromSelected()); + return Config::GetDouble(Config::MIN_BRIGHTNESS) * std::min( 1.0, static_cast(std::abs(offset_from_selected)) / max_visible_distance_from_selected); @@ -345,14 +330,28 @@ bool StyleCalculator::GetTargetVisibilityForOffset( size_t workspace_index) const { // The workspace at the highest possible index is the shallowest workspace // out of both stacks and is always visible. - // The workspace at |kMaxVisibleWorkspaceFromSelected| is hidden because - // it has the same transform as the shallowest workspace and is completely + // The workspace at |GetMaxVisibleOffsetFromSelected()| is hidden because it + // has the same transform as the shallowest workspace and is completely // occluded by it. if (workspace_index == num_workspaces_ - 1) return true; - return offset_from_selected >= kMinVisibleOffsetFromSelected && - offset_from_selected < kMaxVisibleOffsetFromSelected; + return offset_from_selected >= GetMinVisibleOffsetFromSelected() && + offset_from_selected < GetMaxVisibleOffsetFromSelected(); +} + +int StyleCalculator::GetMinVisibleOffsetFromSelected() const { + const base::ListValue& y_offsets = Config::GetListValue( + Config::DEEPER_THAN_SELECTED_Y_OFFSETS); + // Hide workspaces for which there is no y offset specified. + return -1 * static_cast(y_offsets.GetSize()); +} + +int StyleCalculator::GetMaxVisibleOffsetFromSelected() const { + const base::ListValue& y_offsets = Config::GetListValue( + Config::SHALLOWER_THAN_SELECTED_Y_OFFSETS); + // Hide workspaces for which there is no y offset specified. + return y_offsets.GetSize(); } WorkspaceCyclerAnimator::WorkspaceCyclerAnimator(Delegate* delegate) @@ -413,9 +412,12 @@ void WorkspaceCyclerAnimator::AnimateStartingCycler() { layer->SetLayerBrightness(brightness); } + int start_cycler_animation_duration = static_cast(Config::GetDouble( + Config::START_CYCLER_ANIMATION_DURATION)); + scroll_delta_ = 0; animation_type_ = CYCLER_START; - AnimateToUpdatedState(kStartCyclerAnimationDuration); + AnimateToUpdatedState(start_cycler_animation_duration); aura::Window* background = GetDesktopBackground(); if (background) { @@ -431,9 +433,9 @@ void WorkspaceCyclerAnimator::AnimateStartingCycler() { settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - kStartCyclerAnimationDuration)); + start_cycler_animation_duration)); - layer->SetOpacity(kBackgroundOpacity); + layer->SetOpacity(Config::GetDouble(Config::BACKGROUND_OPACITY)); } } @@ -453,8 +455,11 @@ void WorkspaceCyclerAnimator::AnimateStoppingCycler() { return; } + int stop_cycler_animation_duration = static_cast(Config::GetDouble( + Config::STOP_CYCLER_ANIMATION_DURATION)); + animation_type_ = CYCLER_END; - AnimateToUpdatedState(kStopCyclerAnimationDuration); + AnimateToUpdatedState(stop_cycler_animation_duration); aura::Window* background = GetDesktopBackground(); if (background) { @@ -463,7 +468,7 @@ void WorkspaceCyclerAnimator::AnimateStoppingCycler() { settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( - kStopCyclerAnimationDuration)); + stop_cycler_animation_duration)); layer->SetOpacity((selected_workspace_index_ == 0) ? 1.0f : 0.0f); } @@ -475,8 +480,8 @@ void WorkspaceCyclerAnimator::AbortAnimations() { CyclerStopped(initial_active_workspace_index_); } -void WorkspaceCyclerAnimator::AnimateCyclingByScrollDelta(float scroll_delta) { - if (scroll_delta == 0.0f) +void WorkspaceCyclerAnimator::AnimateCyclingByScrollDelta(double scroll_delta) { + if (scroll_delta == 0) return; // Drop any updates received while an animation is running. @@ -490,12 +495,15 @@ void WorkspaceCyclerAnimator::AnimateCyclingByScrollDelta(float scroll_delta) { double old_scroll_delta = scroll_delta_; scroll_delta_ += scroll_delta; + double scroll_distance_to_cycle_to_next_workspace = Config::GetDouble( + Config::SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE); + double min_scroll_delta = -1 * static_cast(selected_workspace_index_) * - kScrollAmountToCycleToNextWorkspace; + scroll_distance_to_cycle_to_next_workspace; double max_scroll_delta = static_cast( workspaces_.size() - 1 - selected_workspace_index_) * - kScrollAmountToCycleToNextWorkspace; + scroll_distance_to_cycle_to_next_workspace; if (scroll_delta_ < min_scroll_delta) scroll_delta_ = min_scroll_delta; @@ -510,11 +518,12 @@ void WorkspaceCyclerAnimator::AnimateCyclingByScrollDelta(float scroll_delta) { // has scrolled the exact amount to select the workspace with no undershoot / // overshoot. int workspace_change = floor(scroll_delta_ / - kScrollAmountToCycleToNextWorkspace + .5); + scroll_distance_to_cycle_to_next_workspace + .5); selected_workspace_index_ += workspace_change; // Set |scroll_delta_| to the amount of undershoot / overshoot. - scroll_delta_ -= workspace_change * kScrollAmountToCycleToNextWorkspace; + scroll_delta_ -= workspace_change * + scroll_distance_to_cycle_to_next_workspace; int animation_duration = GetAnimationDurationForChangeInScrollDelta( scroll_delta_ - old_scroll_delta); @@ -636,8 +645,9 @@ void WorkspaceCyclerAnimator::AnimateTo(size_t workspace_index, int WorkspaceCyclerAnimator::GetAnimationDurationForChangeInScrollDelta( double change) const { - return static_cast( - fabs(change) * kCyclerStepAnimationDurationRatio); + double ratio = Config::GetDouble( + Config::CYCLER_STEP_ANIMATION_DURATION_RATIO); + return static_cast(fabs(change) * ratio); } void WorkspaceCyclerAnimator::CreateLauncherBackground() { diff --git a/ash/wm/workspace/workspace_cycler_animator.h b/ash/wm/workspace/workspace_cycler_animator.h index 0ed0d2216dcace..e6b584ca3d1470 100644 --- a/ash/wm/workspace/workspace_cycler_animator.h +++ b/ash/wm/workspace/workspace_cycler_animator.h @@ -75,7 +75,7 @@ class ASH_EXPORT WorkspaceCyclerAnimator : void AbortAnimations(); // Animate cycling by |scroll_delta|. - void AnimateCyclingByScrollDelta(float scroll_delta); + void AnimateCyclingByScrollDelta(double scroll_delta); // Returns the workspace which should be activated if the user does not do // any more cycling. diff --git a/ash/wm/workspace/workspace_cycler_configuration.cc b/ash/wm/workspace/workspace_cycler_configuration.cc new file mode 100644 index 00000000000000..8c5d1ae1164472 --- /dev/null +++ b/ash/wm/workspace/workspace_cycler_configuration.cc @@ -0,0 +1,160 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/workspace/workspace_cycler_configuration.h" + +#include "ash/ash_switches.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/values.h" + +namespace { + +ListValue* g_shallower_than_selected_y_offsets = NULL; +ListValue* g_deeper_than_selected_y_offsets = NULL; +double g_selected_y_offset = 40; +double g_selected_scale = 0.95; +double g_min_scale = 0.9; +double g_max_scale = 1.0; +double g_min_brightness = -0.4; +double g_background_opacity = 0.8; +double g_distance_to_initiate_cycling = 10; +double g_scroll_amount_to_cycle_to_next_workspace = 10; +double g_cycler_step_animation_duration_ratio = 10; +double g_start_cycler_animation_duration = 100; +double g_stop_cycler_animation_duration = 100; + +} // namespace + +namespace ash { + +// static +bool WorkspaceCyclerConfiguration::IsCyclerEnabled() { + return CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshEnableWorkspaceScrubbing); +} + +// static +bool WorkspaceCyclerConfiguration::IsListProperty(Property property) { + return (property == SHALLOWER_THAN_SELECTED_Y_OFFSETS || + property == DEEPER_THAN_SELECTED_Y_OFFSETS); +} + +// static +void WorkspaceCyclerConfiguration::SetListValue(Property property, + const ListValue& list_value) { + DCHECK(IsListProperty(property)); + if (property == SHALLOWER_THAN_SELECTED_Y_OFFSETS) + g_shallower_than_selected_y_offsets = list_value.DeepCopy(); + else if (property == DEEPER_THAN_SELECTED_Y_OFFSETS) + g_deeper_than_selected_y_offsets = list_value.DeepCopy(); +} + +// static +void WorkspaceCyclerConfiguration::SetDouble(Property property, double value) { + switch (property) { + case SHALLOWER_THAN_SELECTED_Y_OFFSETS: + case DEEPER_THAN_SELECTED_Y_OFFSETS: + NOTREACHED(); + break; + case SELECTED_Y_OFFSET: + g_selected_y_offset = value; + break; + case SELECTED_SCALE: + g_selected_scale = value; + break; + case MIN_SCALE: + g_min_scale = value; + break; + case MAX_SCALE: + g_max_scale = value; + break; + case MIN_BRIGHTNESS: + g_min_brightness = value; + break; + case BACKGROUND_OPACITY: + g_background_opacity = value; + break; + case DISTANCE_TO_INITIATE_CYCLING: + g_distance_to_initiate_cycling = value; + break; + case SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE: + g_scroll_amount_to_cycle_to_next_workspace = value; + break; + case CYCLER_STEP_ANIMATION_DURATION_RATIO: + g_cycler_step_animation_duration_ratio = value; + break; + case START_CYCLER_ANIMATION_DURATION: + g_start_cycler_animation_duration = value; + break; + case STOP_CYCLER_ANIMATION_DURATION: + g_stop_cycler_animation_duration = value; + break; + } +} + +// static +const ListValue& WorkspaceCyclerConfiguration::GetListValue(Property property) { + DCHECK(IsListProperty(property)); + if (property == SHALLOWER_THAN_SELECTED_Y_OFFSETS) { + if (!g_shallower_than_selected_y_offsets) { + // First time the property is accessed. Initialize it to the default + // value. + g_shallower_than_selected_y_offsets = new base::ListValue(); + g_shallower_than_selected_y_offsets->AppendDouble(-40); + g_shallower_than_selected_y_offsets->AppendDouble(-32); + g_shallower_than_selected_y_offsets->AppendDouble(-20); + } + return *g_shallower_than_selected_y_offsets; + } else if (property == DEEPER_THAN_SELECTED_Y_OFFSETS) { + if (!g_deeper_than_selected_y_offsets) { + // First time the property is accessed. Initialize it to the default + // value. + g_deeper_than_selected_y_offsets = new base::ListValue(); + g_deeper_than_selected_y_offsets->AppendDouble(28); + g_deeper_than_selected_y_offsets->AppendDouble(20); + } + return *g_deeper_than_selected_y_offsets; + } + + NOTREACHED(); + CR_DEFINE_STATIC_LOCAL(base::ListValue, default_return_value, ()); + return default_return_value; +} + +// static +double WorkspaceCyclerConfiguration::GetDouble(Property property) { + switch (property) { + case SHALLOWER_THAN_SELECTED_Y_OFFSETS: + case DEEPER_THAN_SELECTED_Y_OFFSETS: + NOTREACHED(); + return 0; + case SELECTED_Y_OFFSET: + return g_selected_y_offset; + case SELECTED_SCALE: + return g_selected_scale; + case MIN_SCALE: + return g_min_scale; + case MAX_SCALE: + return g_max_scale; + case MIN_BRIGHTNESS: + return g_min_brightness; + case BACKGROUND_OPACITY: + return g_background_opacity; + case DISTANCE_TO_INITIATE_CYCLING: + return g_distance_to_initiate_cycling; + case SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE: + return g_scroll_amount_to_cycle_to_next_workspace; + case CYCLER_STEP_ANIMATION_DURATION_RATIO: + return g_cycler_step_animation_duration_ratio; + case START_CYCLER_ANIMATION_DURATION: + return g_start_cycler_animation_duration; + case STOP_CYCLER_ANIMATION_DURATION: + return g_stop_cycler_animation_duration; + } + NOTREACHED(); + return 0; +} + +} // namespace ash diff --git a/ash/wm/workspace/workspace_cycler_configuration.h b/ash/wm/workspace/workspace_cycler_configuration.h new file mode 100644 index 00000000000000..0d2732685a471b --- /dev/null +++ b/ash/wm/workspace/workspace_cycler_configuration.h @@ -0,0 +1,93 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_WORKSPACE_WORKSPACE_CYCLER_CONFIGURATION_H_ +#define ASH_WM_WORKSPACE_WORKSPACE_CYCLER_CONFIGURATION_H_ + +#include "ash/ash_export.h" +#include "base/basictypes.h" + +namespace base { +class ListValue; +} + +namespace ash { + +// Sets and retrieves properties related to cycling workspaces. +class ASH_EXPORT WorkspaceCyclerConfiguration { + public: + enum Property { + // The y offsets for the workspaces which are shallower than the selected + // workspace with respect to the top of the screen workarea. The offset at + // index 0 is for the workspace closest to the selected workspace. The size + // of the ListValue limits the amount of visible workspaces shallower than + // the selected workspace. + SHALLOWER_THAN_SELECTED_Y_OFFSETS, + + // The y offsets for the workspaces which are deeper than the selected + // workspace with respect to the bottom of the screen workarea. The offset + // at index 0 is for the workspace closest to the selected workspace. The + // size of the ListValue limits the amount of visible workspaces deeper + // than the selected workspace. + DEEPER_THAN_SELECTED_Y_OFFSETS, + + // The y offset of the selected workspace with respect to the top of the + // screen workarea. + SELECTED_Y_OFFSET, + + SELECTED_SCALE, + MIN_SCALE, + MAX_SCALE, + MIN_BRIGHTNESS, + + // The background opacity while the user is cycling through workspaces. + BACKGROUND_OPACITY, + + // The vertical scroll distance in pixels to initiate workspace cycling. + DISTANCE_TO_INITIATE_CYCLING, + + // The vertical scroll distance in pixels to cycle to the next / previous + // workspace. + SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE, + + // The ratio of the duration of the animation in milliseconds to the amount + // that the user has scrolled vertically in pixels. + // The duration of the animation is computed by: distance_scrolled * ratio + CYCLER_STEP_ANIMATION_DURATION_RATIO, + + // The duration in milliseconds of the animations when animating starting + // the cycler. + START_CYCLER_ANIMATION_DURATION, + + // The duration in milliseconds of the animations when animating stopping + // the cycler. + STOP_CYCLER_ANIMATION_DURATION, + }; + + // Returns true if the cycler is enabled. + static bool IsCyclerEnabled(); + + // Returns true if |property| is of type base::ListValue. + static bool IsListProperty(Property property); + + // Sets |property| to |list_value|. + static void SetListValue(Property property, + const base::ListValue& list_value); + + // Sets |property| to |value|. + static void SetDouble(Property property, double value); + + // Gets the ListValue associated with |property|. + static const base::ListValue& GetListValue(Property property); + + // Gets the double associated with |property|. + static double GetDouble(Property property); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(WorkspaceCyclerConfiguration); +}; + +} // namespace ash + +#endif // ASH_WM_WORKSPACE_WORKSPACE_CYCLER_ANIMATOR_CONFIGURATION_H_ diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc index 17ba261b769efe..819cdd464678c8 100644 --- a/ash/wm/workspace/workspace_manager.cc +++ b/ash/wm/workspace/workspace_manager.cc @@ -7,7 +7,6 @@ #include #include -#include "ash/ash_switches.h" #include "ash/root_window_controller.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" @@ -23,10 +22,10 @@ #include "ash/wm/workspace/workspace_animations.h" #include "ash/wm/workspace/workspace_cycler.h" #include "ash/wm/workspace/workspace_cycler_animator.h" +#include "ash/wm/workspace/workspace_cycler_configuration.h" #include "ash/wm/workspace/workspace_layout_manager.h" #include "ash/wm/workspace/workspace.h" #include "base/auto_reset.h" -#include "base/command_line.h" #include "base/logging.h" #include "base/stl_util.h" #include "ui/aura/client/aura_constants.h" @@ -127,10 +126,8 @@ WorkspaceManager::WorkspaceManager(Window* contents_view) active_workspace_->window()->Show(); Shell::GetInstance()->AddShellObserver(this); - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableWorkspaceScrubbing)) { + if (ash::WorkspaceCyclerConfiguration::IsCyclerEnabled()) workspace_cycler_.reset(new WorkspaceCycler(this)); - } } WorkspaceManager::~WorkspaceManager() { diff --git a/chrome/browser/resources/gesture_config.js b/chrome/browser/resources/gesture_config.js index b56f3c4e0f8b8a..5858683b80de89 100644 --- a/chrome/browser/resources/gesture_config.js +++ b/chrome/browser/resources/gesture_config.js @@ -139,7 +139,7 @@ GeneralConfig.prototype = { */ function GestureConfig() { /** The title of the section for the gesture preferences. **/ - /** @const */ var GESTURE_TITLE = 'Gesture Properties'; + /** @const */ var GESTURE_TITLE = 'Gesture Configuration'; /** Common prefix of gesture preferences. **/ /** @const */ var GESTURE_PREFIX = 'gesture.'; @@ -285,7 +285,7 @@ function GestureConfig() { * @return {object} A GeneralConfig object. */ function OverscrollConfig() { - /** @const */ var OVERSCROLL_TITLE = 'Overscroll Properties'; + /** @const */ var OVERSCROLL_TITLE = 'Overscroll Configuration'; /** @const */ var OVERSCROLL_PREFIX = 'overscroll.'; @@ -322,12 +322,78 @@ function OverscrollConfig() { OVERSCROLL_FIELDS); } +/** + * Returns a GeneralConfig for configuring workspace_cycler.* preferences. + * @return {object} A GeneralConfig object. + */ +function WorkspaceCyclerConfig() { + /** @const */ var WORKSPACE_CYCLER_TITLE = 'Workspace Cycler Configuration'; + + /** @const */ var WORKSPACE_CYCLER_PREFIX = 'workspace_cycler.'; + + var WORKSPACE_CYCLER_FIELDS = [ + { + key: 'selected_scale', + label: 'Scale of the selected workspace', + units: '%' + }, + { + key: 'min_scale', + label: 'Minimum workspace scale (scale of deepest workspace)', + units: '%' + }, + { + key: 'max_scale', + label: 'Maximimum workspace scale (scale of shallowest workspace)', + units: '%' + }, + { + key: 'min_brightness', + label: 'Minimum workspace brightness (deepest & shallowest workspace)', + units: '%' + }, + { + key: 'background_opacity', + label: 'Desktop background opacity when cycling through workspaces', + units: '%' + }, + { + key: 'distance_to_initiate_cycling', + label: 'Vertical distance to scroll to initiate cycling', + units: 'pixels' + }, + { + key: 'scroll_distance_to_cycle_to_next_workspace', + label: 'Vertical distance to scroll to cycle to the next workspace', + units: 'pixels' + }, + { key: 'cycler_step_animation_duration_ratio', + label: 'Cycler step animation duration ratio', + units: 'ms / pixels vertical scroll' + }, + { key: 'start_cycler_animation_duration', + label: 'Duration of the animations to start cycling', + units: 'ms' + }, + { key: 'stop_cycler_animation_duration', + label: 'Duration of the animations to stop cycling', + units: 'ms' + } + ]; + + return new GeneralConfig(WORKSPACE_CYCLER_TITLE, + WORKSPACE_CYCLER_PREFIX, + WORKSPACE_CYCLER_FIELDS); +} + /** * Returns a GeneralConfig for configuring flingcurve.* preferences. * @return {object} A GeneralConfig object. */ function FlingConfig() { - var FLING_PREFIX = 'flingcurve.'; + /** @const */ var FLING_TITLE = 'Fling Configuration'; + + /** @const */ var FLING_PREFIX = 'flingcurve.'; var FLING_FIELDS = [ { @@ -362,7 +428,7 @@ function FlingConfig() { }, ]; - return new GeneralConfig(FLING_PREFIX, FLING_FIELDS); + return new GeneralConfig(FLING_TITLE, FLING_PREFIX, FLING_FIELDS); } @@ -385,10 +451,14 @@ var gesture_config = (function() { var f = FlingConfig(); f.buildAll(); + var c = WorkspaceCyclerConfig(); + c.buildAll(); + $('reset-button').onclick = function() { g.onReset(); o.onReset(); f.onReset(); + c.onReset(); }; } diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc index 4d79c02de5656f..7f256b82c789a9 100644 --- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc +++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc @@ -4,6 +4,8 @@ #include "chrome/browser/ui/gesture_prefs_observer_factory_aura.h" +#include + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/compiler_specific.h" @@ -20,6 +22,14 @@ #include "content/public/common/renderer_preferences.h" #include "ui/base/gestures/gesture_configuration.h" +#if defined(USE_ASH) +#include "ash/wm/workspace/workspace_cycler_configuration.h" +#endif // USE_ASH + +#if defined(USE_ASH) +using ash::WorkspaceCyclerConfiguration; +#endif // USE_ASH + using ui::GestureConfiguration; namespace { @@ -29,15 +39,11 @@ struct OverscrollPref { content::OverscrollConfig config; }; -// This class manages gesture configuration preferences. -class GesturePrefsObserver : public ProfileKeyedService { - public: - explicit GesturePrefsObserver(PrefService* prefs); - virtual ~GesturePrefsObserver(); - - static const OverscrollPref* GetOverscrollPrefs() { +const std::vector& GetOverscrollPrefs() { + CR_DEFINE_STATIC_LOCAL(std::vector, overscroll_prefs, ()); + if (overscroll_prefs.empty()) { using namespace content; - static OverscrollPref overscroll_prefs[] = { + const OverscrollPref kOverscrollPrefs[] = { { prefs::kOverscrollHorizontalThresholdComplete, OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE }, { prefs::kOverscrollVerticalThresholdComplete, @@ -48,12 +54,62 @@ class GesturePrefsObserver : public ProfileKeyedService { OVERSCROLL_CONFIG_HORIZ_RESIST_AFTER }, { prefs::kOverscrollVerticalResistThreshold, OVERSCROLL_CONFIG_VERT_RESIST_AFTER }, - { NULL, - OVERSCROLL_CONFIG_NONE }, }; + overscroll_prefs.assign(kOverscrollPrefs, + kOverscrollPrefs + arraysize(kOverscrollPrefs)); + } + return overscroll_prefs; +} + +#if defined(USE_ASH) +struct WorkspaceCyclerPref { + const char* pref_name; + WorkspaceCyclerConfiguration::Property property; +}; - return overscroll_prefs; +const std::vector& GetWorkspaceCyclerPrefs() { + CR_DEFINE_STATIC_LOCAL(std::vector, cycler_prefs, ()); + if (cycler_prefs.empty() && WorkspaceCyclerConfiguration::IsCyclerEnabled()) { + const WorkspaceCyclerPref kCyclerPrefs[] = { + { prefs::kWorkspaceCyclerShallowerThanSelectedYOffsets, + WorkspaceCyclerConfiguration::SHALLOWER_THAN_SELECTED_Y_OFFSETS }, + { prefs::kWorkspaceCyclerDeeperThanSelectedYOffsets, + WorkspaceCyclerConfiguration::DEEPER_THAN_SELECTED_Y_OFFSETS }, + { prefs::kWorkspaceCyclerSelectedYOffset, + WorkspaceCyclerConfiguration::SELECTED_Y_OFFSET }, + { prefs::kWorkspaceCyclerSelectedScale, + WorkspaceCyclerConfiguration::SELECTED_SCALE }, + { prefs::kWorkspaceCyclerMinScale, + WorkspaceCyclerConfiguration::MIN_SCALE }, + { prefs::kWorkspaceCyclerMaxScale, + WorkspaceCyclerConfiguration::MAX_SCALE }, + { prefs::kWorkspaceCyclerMinBrightness, + WorkspaceCyclerConfiguration::MIN_BRIGHTNESS }, + { prefs::kWorkspaceCyclerBackgroundOpacity, + WorkspaceCyclerConfiguration::BACKGROUND_OPACITY }, + { prefs::kWorkspaceCyclerDistanceToInitiateCycling, + WorkspaceCyclerConfiguration::DISTANCE_TO_INITIATE_CYCLING }, + { prefs::kWorkspaceCyclerScrollDistanceToCycleToNextWorkspace, + WorkspaceCyclerConfiguration:: + SCROLL_DISTANCE_TO_CYCLE_TO_NEXT_WORKSPACE }, + { prefs::kWorkspaceCyclerCyclerStepAnimationDurationRatio, + WorkspaceCyclerConfiguration::CYCLER_STEP_ANIMATION_DURATION_RATIO }, + { prefs::kWorkspaceCyclerStartCyclerAnimationDuration, + WorkspaceCyclerConfiguration::START_CYCLER_ANIMATION_DURATION }, + { prefs::kWorkspaceCyclerStopCyclerAnimationDuration, + WorkspaceCyclerConfiguration::STOP_CYCLER_ANIMATION_DURATION }, + }; + cycler_prefs.assign(kCyclerPrefs, kCyclerPrefs + arraysize(kCyclerPrefs)); } + return cycler_prefs; +} +#endif // USE_ASH + +// This class manages gesture configuration preferences. +class GesturePrefsObserver : public ProfileKeyedService { + public: + explicit GesturePrefsObserver(PrefService* prefs); + virtual ~GesturePrefsObserver(); // ProfileKeyedService implementation. virtual void Shutdown() OVERRIDE; @@ -71,6 +127,7 @@ class GesturePrefsObserver : public ProfileKeyedService { // Notification helper to push overscroll preferences into // content. void UpdateOverscrollPrefs(); + void UpdateWorkspaceCyclerPrefs(); PrefChangeRegistrar registrar_; PrefService* prefs_; @@ -109,14 +166,6 @@ const char* kPrefsToObserve[] = { prefs::kSemiLongPressTimeInSeconds, }; -const char* kOverscrollPrefs[] = { - prefs::kOverscrollHorizontalThresholdComplete, - prefs::kOverscrollVerticalThresholdComplete, - prefs::kOverscrollMinimumThresholdStart, - prefs::kOverscrollHorizontalResistThreshold, - prefs::kOverscrollVerticalResistThreshold, -}; - const char* kFlingTouchpadPrefs[] = { prefs::kFlingCurveTouchpadAlpha, prefs::kFlingCurveTouchpadBeta, @@ -141,13 +190,22 @@ GesturePrefsObserver::GesturePrefsObserver(PrefService* prefs) for (size_t i = 0; i < arraysize(kPrefsToObserve); ++i) registrar_.Add(kPrefsToObserve[i], callback); - for (size_t i = 0; i < arraysize(kOverscrollPrefs); ++i) - registrar_.Add(kOverscrollPrefs[i], callback); + + const std::vector& overscroll_prefs = GetOverscrollPrefs(); + for (size_t i = 0; i < overscroll_prefs.size(); ++i) + registrar_.Add(overscroll_prefs[i].pref_name, callback); for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); ++i) registrar_.Add(kFlingTouchpadPrefs[i], notify_callback); for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); ++i) registrar_.Add(kFlingTouchscreenPrefs[i], notify_callback); + +#if defined(USE_ASH) + const std::vector& cycler_prefs = + GetWorkspaceCyclerPrefs(); + for (size_t i = 0; i < cycler_prefs.size(); ++i) + registrar_.Add(cycler_prefs[i].pref_name, callback); +#endif // USE_ASH } GesturePrefsObserver::~GesturePrefsObserver() {} @@ -230,17 +288,35 @@ void GesturePrefsObserver::Update() { prefs::kRailStartProportion)); UpdateOverscrollPrefs(); + UpdateWorkspaceCyclerPrefs(); } void GesturePrefsObserver::UpdateOverscrollPrefs() { - const OverscrollPref* overscroll_prefs = - GesturePrefsObserver::GetOverscrollPrefs(); - for (int i = 0; overscroll_prefs[i].pref_name; ++i) { + const std::vector& overscroll_prefs = GetOverscrollPrefs(); + for (size_t i = 0; i < overscroll_prefs.size(); ++i) { content::SetOverscrollConfig(overscroll_prefs[i].config, static_cast(prefs_->GetDouble(overscroll_prefs[i].pref_name))); } } +void GesturePrefsObserver::UpdateWorkspaceCyclerPrefs() { +#if defined(USE_ASH) + const std::vector& cycler_prefs = + GetWorkspaceCyclerPrefs(); + for (size_t i = 0; i < cycler_prefs.size(); ++i) { + WorkspaceCyclerConfiguration::Property property = + cycler_prefs[i].property; + if (WorkspaceCyclerConfiguration::IsListProperty(property)) { + WorkspaceCyclerConfiguration::SetListValue(property, + *prefs_->GetList(cycler_prefs[i].pref_name)); + } else { + WorkspaceCyclerConfiguration::SetDouble(property, + prefs_->GetDouble(cycler_prefs[i].pref_name)); + } + } +#endif // USE_ASH +} + void GesturePrefsObserver::Notify() { // Must do a notify to distribute the changes to all renderers. content::NotificationService* service = @@ -271,10 +347,9 @@ ProfileKeyedService* GesturePrefsObserverFactoryAura::BuildServiceInstanceFor( void GesturePrefsObserverFactoryAura::RegisterOverscrollPrefs( PrefRegistrySyncable* registry) { - const OverscrollPref* overscroll_prefs = - GesturePrefsObserver::GetOverscrollPrefs(); + const std::vector& overscroll_prefs = GetOverscrollPrefs(); - for (int i = 0; overscroll_prefs[i].pref_name; ++i) { + for (size_t i = 0; i < overscroll_prefs.size(); ++i) { registry->RegisterDoublePref( overscroll_prefs[i].pref_name, content::GetOverscrollConfig(overscroll_prefs[i].config), @@ -297,6 +372,29 @@ void GesturePrefsObserverFactoryAura::RegisterFlingCurveParameters( PrefRegistrySyncable::UNSYNCABLE_PREF); } +void GesturePrefsObserverFactoryAura::RegisterWorkspaceCyclerPrefs( + PrefRegistrySyncable* registry) { +#if defined(USE_ASH) + const std::vector& cycler_prefs = + GetWorkspaceCyclerPrefs(); + for (size_t i = 0; i < cycler_prefs.size(); ++i) { + WorkspaceCyclerConfiguration::Property property = + cycler_prefs[i].property; + if (WorkspaceCyclerConfiguration::IsListProperty(property)) { + registry->RegisterListPref( + cycler_prefs[i].pref_name, + WorkspaceCyclerConfiguration::GetListValue(property).DeepCopy(), + PrefRegistrySyncable::UNSYNCABLE_PREF); + } else { + registry->RegisterDoublePref( + cycler_prefs[i].pref_name, + WorkspaceCyclerConfiguration::GetDouble(property), + PrefRegistrySyncable::UNSYNCABLE_PREF); + } + } +#endif // USE_ASH +} + void GesturePrefsObserverFactoryAura::DeprecatedRegisterUserPrefs( PrefService* prefs, PrefRegistrySyncable* registry) { @@ -415,6 +513,7 @@ void GesturePrefsObserverFactoryAura::DeprecatedRegisterUserPrefs( RegisterOverscrollPrefs(registry); RegisterFlingCurveParameters(registry); + RegisterWorkspaceCyclerPrefs(registry); } bool GesturePrefsObserverFactoryAura::ServiceIsCreatedWithProfile() const { diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.h b/chrome/browser/ui/gesture_prefs_observer_factory_aura.h index 46364ecd000a1f..1aac876b7227fb 100644 --- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.h +++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.h @@ -24,8 +24,9 @@ class GesturePrefsObserverFactoryAura : public ProfileKeyedServiceFactory { GesturePrefsObserverFactoryAura(); virtual ~GesturePrefsObserverFactoryAura(); - void RegisterOverscrollPrefs(PrefRegistrySyncable* prefs); - void RegisterFlingCurveParameters(PrefRegistrySyncable* prefs); + void RegisterOverscrollPrefs(PrefRegistrySyncable* registry); + void RegisterFlingCurveParameters(PrefRegistrySyncable* registry); + void RegisterWorkspaceCyclerPrefs(PrefRegistrySyncable* registry); // ProfileKeyedServiceFactory: virtual ProfileKeyedService* BuildServiceInstanceFor( diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index a937ff4edbc671..12a9a1309e1a57 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -2173,7 +2173,7 @@ const char kMediaGalleriesUniqueId[] = "media_galleries.gallery_id"; const char kMediaGalleriesRememberedGalleries[] = "media_galleries.remembered_galleries"; -#if defined(USE_AURA) +#if defined(USE_ASH) // |kShelfAlignment| and |kShelfAutoHideBehavior| have a local variant. The // local variant is not synced and is used if set. If the local variant is not // set its value is set from the synced value (once prefs have been @@ -2196,6 +2196,38 @@ const char kShowLogoutButtonInTray[] = "show_logout_button_in_tray"; // kShelfAutoHideBehavior. const char kShelfPreferences[] = "shelf_preferences"; +// Tuning settings for the animations when a user is cycling through workspaces +// via a three finger vertical scroll. +const char kWorkspaceCyclerShallowerThanSelectedYOffsets[] = + "workspace_cycler.shallower_than_selected_y_offsets"; +const char kWorkspaceCyclerDeeperThanSelectedYOffsets[] = + "workspace_cycler.deeper_than_selected_y_offsets"; +const char kWorkspaceCyclerSelectedYOffset[] = + "workspace_cycler.selected_y_offset"; +const char kWorkspaceCyclerSelectedScale[] = + "workspace_cycler.selected_scale"; +const char kWorkspaceCyclerMinScale[] = + "workspace_cycler.min_scale"; +const char kWorkspaceCyclerMaxScale[] = + "workspace_cycler.max_scale"; +const char kWorkspaceCyclerMinBrightness[] = + "workspace_cycler.min_brightness"; +const char kWorkspaceCyclerBackgroundOpacity[] = + "workspace_cycler.background_opacity"; +const char kWorkspaceCyclerDistanceToInitiateCycling[] = + "workspace_cycler.distance_to_initiate_cycling"; +const char kWorkspaceCyclerScrollDistanceToCycleToNextWorkspace[] = + "workspace_cycler.scroll_distance_to_cycle_to_next_workspace"; +const char kWorkspaceCyclerCyclerStepAnimationDurationRatio[] = + "workspace_cycler.cycler_step_animation_duration_ratio"; +const char kWorkspaceCyclerStartCyclerAnimationDuration[] = + "workspace_cycler.start_cycler_animation_duration"; +const char kWorkspaceCyclerStopCyclerAnimationDuration[] = + "workspace_cycler.stop_cycler_animation_duration"; +#endif + +#if defined(USE_AURA) +// Tuning settings for gestures. const char kFlingVelocityCap[] = "gesture.fling_velocity_cap"; const char kLongPressTimeInSeconds[] = "gesture.long_press_time_in_seconds"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index ca09c2f6828c7d..8f26c1b6310f9c 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -782,7 +782,7 @@ extern const char kComponentUpdaterState[]; extern const char kMediaGalleriesUniqueId[]; extern const char kMediaGalleriesRememberedGalleries[]; -#if defined(USE_AURA) +#if defined(USE_ASH) extern const char kShelfAlignment[]; extern const char kShelfAlignmentLocal[]; extern const char kShelfAutoHideBehavior[]; @@ -791,6 +791,22 @@ extern const char kPinnedLauncherApps[]; extern const char kShowLogoutButtonInTray[]; extern const char kShelfPreferences[]; +extern const char kWorkspaceCyclerShallowerThanSelectedYOffsets[]; +extern const char kWorkspaceCyclerDeeperThanSelectedYOffsets[]; +extern const char kWorkspaceCyclerSelectedYOffset[]; +extern const char kWorkspaceCyclerSelectedScale[]; +extern const char kWorkspaceCyclerMinScale[]; +extern const char kWorkspaceCyclerMaxScale[]; +extern const char kWorkspaceCyclerMinBrightness[]; +extern const char kWorkspaceCyclerBackgroundOpacity[]; +extern const char kWorkspaceCyclerDistanceToInitiateCycling[]; +extern const char kWorkspaceCyclerScrollDistanceToCycleToNextWorkspace[]; +extern const char kWorkspaceCyclerCyclerStepAnimationDurationRatio[]; +extern const char kWorkspaceCyclerStartCyclerAnimationDuration[]; +extern const char kWorkspaceCyclerStopCyclerAnimationDuration[]; +#endif + +#if defined(USE_AURA) extern const char kFlingVelocityCap[]; extern const char kLongPressTimeInSeconds[]; extern const char kMaxDistanceBetweenTapsForDoubleTap[];