Commit 83eef80d authored by pkotwicz@chromium.org's avatar pkotwicz@chromium.org

Implement workspace scrubbing

BUG=160903
Test=Manual

Review URL: https://chromiumcodereview.appspot.com/11417150

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170688 0039d316-1c4b-4281-b951-d872f2087c98
parent c6bf815d
...@@ -403,6 +403,8 @@ ...@@ -403,6 +403,8 @@
'wm/workspace/workspace.h', 'wm/workspace/workspace.h',
'wm/workspace/workspace_animations.cc', 'wm/workspace/workspace_animations.cc',
'wm/workspace/workspace_animations.h', 'wm/workspace/workspace_animations.h',
'wm/workspace/workspace_cycler.cc',
'wm/workspace/workspace_cycler.h',
'wm/workspace/workspace_event_handler.cc', 'wm/workspace/workspace_event_handler.cc',
'wm/workspace/workspace_event_handler.h', 'wm/workspace/workspace_event_handler.h',
'wm/workspace/workspace_layout_manager.cc', 'wm/workspace/workspace_layout_manager.cc',
......
...@@ -46,6 +46,9 @@ const char kAshDisablePanelFitting[] = "ash-disable-panel-fitting"; ...@@ -46,6 +46,9 @@ const char kAshDisablePanelFitting[] = "ash-disable-panel-fitting";
// Enable advanced gestures (e.g. for window management). // Enable advanced gestures (e.g. for window management).
const char kAshEnableAdvancedGestures[] = "ash-enable-advanced-gestures"; const char kAshEnableAdvancedGestures[] = "ash-enable-advanced-gestures";
// Enable workspace switching via a three finger vertical scroll.
const char kAshEnableWorkspaceScrubbing[] = "ash-enable-workspace-scrubbing";
#if defined(OS_LINUX) #if defined(OS_LINUX)
// Enable memory monitoring. // Enable memory monitoring.
const char kAshEnableMemoryMonitor[] = "ash-enable-memory-monitor"; const char kAshEnableMemoryMonitor[] = "ash-enable-memory-monitor";
......
...@@ -33,6 +33,7 @@ ASH_EXPORT extern const char kAshEnableMemoryMonitor[]; ...@@ -33,6 +33,7 @@ ASH_EXPORT extern const char kAshEnableMemoryMonitor[];
ASH_EXPORT extern const char kAshEnablePerAppLauncher[]; ASH_EXPORT extern const char kAshEnablePerAppLauncher[];
ASH_EXPORT extern const char kAshEnableOak[]; ASH_EXPORT extern const char kAshEnableOak[];
ASH_EXPORT extern const char kAshEnableTrayDragging[]; ASH_EXPORT extern const char kAshEnableTrayDragging[];
ASH_EXPORT extern const char kAshEnableWorkspaceScrubbing[];
ASH_EXPORT extern const char kAshImmersive[]; ASH_EXPORT extern const char kAshImmersive[];
ASH_EXPORT extern const char kAshLauncherPerDisplay[]; ASH_EXPORT extern const char kAshLauncherPerDisplay[];
ASH_EXPORT extern const char kAshNewLockAnimationsEnabled[]; ASH_EXPORT extern const char kAshNewLockAnimationsEnabled[];
......
// Copyright (c) 2012 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.h"
#include "ash/shell.h"
#include "ash/wm/workspace/workspace_manager.h"
#include "ui/base/events/event.h"
#include "ui/base/events/event_utils.h"
namespace ash {
namespace internal {
namespace {
// The required vertical distance to scrub to the next workspace.
const int kWorkspaceStepSize = 10;
// Returns true is scrubbing is enabled.
bool IsScrubbingEnabled() {
// Scrubbing is disabled if the screen is locked or a modal dialog is open.
return !Shell::GetInstance()->IsScreenLocked() &&
!Shell::GetInstance()->IsSystemModalWindowOpen();
}
} // namespace
WorkspaceCycler::WorkspaceCycler(WorkspaceManager* workspace_manager)
: workspace_manager_(workspace_manager),
scrubbing_(false),
scroll_x_(0),
scroll_y_(0) {
ash::Shell::GetInstance()->AddPreTargetHandler(this);
}
WorkspaceCycler::~WorkspaceCycler() {
scrubbing_ = false;
ash::Shell::GetInstance()->RemovePreTargetHandler(this);
}
ui::EventResult WorkspaceCycler::OnScrollEvent(ui::ScrollEvent* event) {
if (event->finger_count() != 3 ||
event->type() != ui::ET_SCROLL) {
scrubbing_ = false;
return ui::ER_UNHANDLED;
}
if (!IsScrubbingEnabled()) {
scrubbing_ = false;
return ui::ER_UNHANDLED;
}
if (!scrubbing_) {
scrubbing_ = true;
scroll_x_ = 0;
scroll_y_ = 0;
}
if (ui::IsNaturalScrollEnabled()) {
scroll_x_ += event->x_offset();
scroll_y_ += event->y_offset();
} else {
scroll_x_ -= event->x_offset();
scroll_y_ -= event->y_offset();
}
// TODO(pkotwicz): Implement scrubbing through several workspaces as the
// result of a single scroll event.
if (std::abs(scroll_y_) > kWorkspaceStepSize) {
workspace_manager_->CycleToWorkspace(scroll_y_ > 0 ?
WorkspaceManager::CYCLE_NEXT : WorkspaceManager::CYCLE_PREVIOUS);
scroll_x_ = 0;
scroll_y_ = 0;
return ui::ER_HANDLED;
}
if (std::abs(scroll_x_) > kWorkspaceStepSize) {
// Update |scroll_x_| and |scroll_y_| such that workspaces are only cycled
// through when there recently was a significant amount of vertical movement
// as opposed to vertical movement accumulated over a long horizontal three
// finger scroll.
scroll_x_ = 0;
scroll_y_ = 0;
}
// The active workspace was not changed, do not consume the event.
return ui::ER_UNHANDLED;
}
} // namespace internal
} // namespace ash
// Copyright (c) 2012 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_H_
#define ASH_WM_WORKSPACE_WORKSPACE_CYCLER_H_
#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ui/base/events/event_handler.h"
namespace ash {
namespace internal {
class WorkspaceManager;
// Class to enable quick workspace switching (scrubbing) via 3 finger vertical
// scroll.
class ASH_EXPORT WorkspaceCycler : public ui::EventHandler {
public:
explicit WorkspaceCycler(WorkspaceManager* workspace_manager);
virtual ~WorkspaceCycler();
private:
// ui::EventHandler overrides:
virtual ui::EventResult OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
WorkspaceManager* workspace_manager_;
// Whether the user is scrubbing through workspaces.
bool scrubbing_;
// The amount of scrolling which has occurred since the last time the
// workspace was switched. If scrubbing has just begun, |scroll_x_| and
// |scroll_y_| are set to 0.
int scroll_x_;
int scroll_y_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceCycler);
};
} // namespace internal
} // namespace ash
#endif // ASH_WM_WORKSPACE_WORKSPACE_CYCLER_H_
...@@ -262,6 +262,33 @@ Window* WorkspaceManager::GetParentForNewWindow(Window* window) { ...@@ -262,6 +262,33 @@ Window* WorkspaceManager::GetParentForNewWindow(Window* window) {
return desktop_workspace()->window(); return desktop_workspace()->window();
} }
bool WorkspaceManager::CycleToWorkspace(CycleDirection direction) {
aura::Window* active_window = wm::GetActiveWindow();
if (!active_workspace_->window()->Contains(active_window))
active_window = NULL;
Workspaces::const_iterator workspace_i(FindWorkspace(active_workspace_));
int workspace_offset = 0;
if (direction == CYCLE_PREVIOUS) {
workspace_offset = 1;
if (workspace_i == workspaces_.end() - 1)
return false;
} else {
workspace_offset = -1;
if (workspace_i == workspaces_.begin())
return false;
}
Workspaces::const_iterator next_workspace_i(workspace_i + workspace_offset);
SetActiveWorkspace(*next_workspace_i, SWITCH_OTHER, base::TimeDelta());
// The activation controller will pick a window from the just activated
// workspace to activate as a result of DeactivateWindow().
if (active_window)
wm::DeactivateWindow(active_window);
return true;
}
void WorkspaceManager::DoInitialAnimation() { void WorkspaceManager::DoInitialAnimation() {
if (active_workspace_->is_maximized()) { if (active_workspace_->is_maximized()) {
RootWindowController* root_controller = GetRootWindowController( RootWindowController* root_controller = GetRootWindowController(
......
...@@ -53,6 +53,11 @@ class Workspace; ...@@ -53,6 +53,11 @@ class Workspace;
// are maximized and restored they are reparented to the right Window. // are maximized and restored they are reparented to the right Window.
class ASH_EXPORT WorkspaceManager : public ash::ShellObserver { class ASH_EXPORT WorkspaceManager : public ash::ShellObserver {
public: public:
enum CycleDirection {
CYCLE_NEXT,
CYCLE_PREVIOUS
};
explicit WorkspaceManager(aura::Window* viewport); explicit WorkspaceManager(aura::Window* viewport);
virtual ~WorkspaceManager(); virtual ~WorkspaceManager();
...@@ -78,6 +83,11 @@ class ASH_EXPORT WorkspaceManager : public ash::ShellObserver { ...@@ -78,6 +83,11 @@ class ASH_EXPORT WorkspaceManager : public ash::ShellObserver {
// when a new Window is being added. // when a new Window is being added.
aura::Window* GetParentForNewWindow(aura::Window* window); aura::Window* GetParentForNewWindow(aura::Window* window);
// Called by the workspace cycler to activate the next workspace in
// |direction|. Returns false if there are no more workspaces to cycle
// to in |direction|.
bool CycleToWorkspace(CycleDirection direction);
// Starts the animation that occurs on first login. // Starts the animation that occurs on first login.
void DoInitialAnimation(); void DoInitialAnimation();
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "ash/ash_switches.h" #include "ash/ash_switches.h"
#include "ash/wm/window_util.h" #include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_cycler.h"
#include "ash/wm/workspace/workspace_manager.h" #include "ash/wm/workspace/workspace_manager.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "ui/aura/client/activation_client.h" #include "ui/aura/client/activation_client.h"
...@@ -17,9 +18,14 @@ namespace ash { ...@@ -17,9 +18,14 @@ namespace ash {
namespace internal { namespace internal {
WorkspaceController::WorkspaceController(aura::Window* viewport) WorkspaceController::WorkspaceController(aura::Window* viewport)
: viewport_(viewport) { : viewport_(viewport),
workspace_cycler_(NULL) {
aura::RootWindow* root_window = viewport->GetRootWindow(); aura::RootWindow* root_window = viewport->GetRootWindow();
workspace_manager_.reset(new WorkspaceManager(viewport)); workspace_manager_.reset(new WorkspaceManager(viewport));
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAshEnableWorkspaceScrubbing)) {
workspace_cycler_.reset(new WorkspaceCycler(workspace_manager_.get()));
}
aura::client::GetActivationClient(root_window)->AddObserver(this); aura::client::GetActivationClient(root_window)->AddObserver(this);
} }
......
...@@ -20,6 +20,7 @@ namespace internal { ...@@ -20,6 +20,7 @@ namespace internal {
class ShelfLayoutManager; class ShelfLayoutManager;
class WorkspaceControllerTestHelper; class WorkspaceControllerTestHelper;
class WorkspaceCycler;
class WorkspaceEventHandler; class WorkspaceEventHandler;
class WorkspaceManager; class WorkspaceManager;
...@@ -56,6 +57,10 @@ class ASH_EXPORT WorkspaceController ...@@ -56,6 +57,10 @@ class ASH_EXPORT WorkspaceController
scoped_ptr<WorkspaceManager> workspace_manager_; scoped_ptr<WorkspaceManager> workspace_manager_;
// Cycles through the WorkspaceManager's workspaces in response to a three
// finger vertical scroll.
scoped_ptr<WorkspaceCycler> workspace_cycler_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceController); DISALLOW_COPY_AND_ASSIGN(WorkspaceController);
}; };
......
...@@ -6726,11 +6726,17 @@ Keep your key file in a safe place. You will need it to create new versions of y ...@@ -6726,11 +6726,17 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_FLAGS_ENABLE_ADVANCED_GESTURES_DESCRIPTION" desc="Title for the flag to enable advanced gestures."> <message name="IDS_FLAGS_ENABLE_ADVANCED_GESTURES_DESCRIPTION" desc="Title for the flag to enable advanced gestures.">
Enables advanced gestures (e.g. 4-finger pinch to minimize window etc.). Enables advanced gestures (e.g. 4-finger pinch to minimize window etc.).
</message> </message>
<message name="IDS_FLAGS_ENABLE_TAB_SCRUBBING_NAME" desc="Title for the flag to enable advanced gestures."> <message name="IDS_FLAGS_ENABLE_TAB_SCRUBBING_NAME" desc="Title for the flag to enable tab scrubbing.">
Enable tab scrubbing Enable tab scrubbing
</message> </message>
<message name="IDS_FLAGS_ENABLE_TAB_SCRUBBING_DESCRIPTION" desc="Title for the flag to enable advanced gestures."> <message name="IDS_FLAGS_ENABLE_TAB_SCRUBBING_DESCRIPTION" desc="Description for the flag to enable tab scrubbing.">
Enables tab switching via 3 finger scroll. Enables tab switching via 3 finger horizontal scroll.
</message>
<message name="IDS_FLAGS_ENABLE_WORKSPACE_SCRUBBING_NAME" desc="Title for the flag to enable workspace scrubbing.">
Enable workspace scrubbing
</message>
<message name="IDS_FLAGS_ENABLE_WORKSPACE_SCRUBBING_DESCRIPTION" desc="Description for the flag to enable workspace scrubbing.">
Enables workspace switching via 3 finger vertical scroll.
</message> </message>
<message name="IDS_FLAGS_ENABLE_IMMERSIVE_MODE_NAME" desc="Title for the flag to enable immersive mode."> <message name="IDS_FLAGS_ENABLE_IMMERSIVE_MODE_NAME" desc="Title for the flag to enable immersive mode.">
Enable immersive windows Enable immersive windows
......
...@@ -1028,6 +1028,12 @@ const Experiment kExperiments[] = { ...@@ -1028,6 +1028,12 @@ const Experiment kExperiments[] = {
kOsCrOS, kOsCrOS,
SINGLE_VALUE_TYPE(switches::kAshEnableTabScrubbing), SINGLE_VALUE_TYPE(switches::kAshEnableTabScrubbing),
}, },
{ "ash-enable-workspace-scrubbing",
IDS_FLAGS_ENABLE_WORKSPACE_SCRUBBING_NAME,
IDS_FLAGS_ENABLE_WORKSPACE_SCRUBBING_DESCRIPTION,
kOsCrOS,
SINGLE_VALUE_TYPE(ash::switches::kAshEnableWorkspaceScrubbing),
},
{ "ash-enable-immersive-mode", { "ash-enable-immersive-mode",
IDS_FLAGS_ENABLE_IMMERSIVE_MODE_NAME, IDS_FLAGS_ENABLE_IMMERSIVE_MODE_NAME,
IDS_FLAGS_ENABLE_IMMERSIVE_MODE_DESCRIPTION, IDS_FLAGS_ENABLE_IMMERSIVE_MODE_DESCRIPTION,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment