diff options
author | Sadrul Habib Chowdhury <sadrul@chromium.org> | 2014-09-03 17:38:05 -0400 |
---|---|---|
committer | Sadrul Habib Chowdhury <sadrul@chromium.org> | 2014-09-03 21:44:20 +0000 |
commit | ab2250a2888e5483aaf2fe87ffb39154fa656d56 (patch) | |
tree | 7d08dec7383decf418f141266d395e82a5b4357b | |
parent | 2db87d712e255f7ff778f91fd74e8818a8099ff0 (diff) | |
download | chromium_src-ab2250a2888e5483aaf2fe87ffb39154fa656d56.zip chromium_src-ab2250a2888e5483aaf2fe87ffb39154fa656d56.tar.gz chromium_src-ab2250a2888e5483aaf2fe87ffb39154fa656d56.tar.bz2 |
athena: Improve the overview mode support for split-view mode.
The notable changes:
. Do not allow horizontal dragging of the split windows.
. Do not show the 'Split' button when dragging a non-split window. Instead,
highlight the split windows as drop targets.
. When a window is dropped on top of a left/right split window, switch to that
window in that part of the split.
BUG=404119
R=oshima@chromium.org
Review URL: https://codereview.chromium.org/537073002
Cr-Commit-Position: refs/heads/master@{#293202}
-rw-r--r-- | athena/wm/overview_toolbar.cc | 22 | ||||
-rw-r--r-- | athena/wm/overview_toolbar.h | 4 | ||||
-rw-r--r-- | athena/wm/window_overview_mode.cc | 103 |
3 files changed, 119 insertions, 10 deletions
diff --git a/athena/wm/overview_toolbar.cc b/athena/wm/overview_toolbar.cc index 339d1dd..d381b1c 100644 --- a/athena/wm/overview_toolbar.cc +++ b/athena/wm/overview_toolbar.cc @@ -98,6 +98,7 @@ class ActionButton : public ui::LayerDelegate { OverviewToolbar::OverviewToolbar(aura::Window* container) : shown_(false), + disabled_action_bitfields_(0), close_(new ActionButton(IDR_ATHENA_OVERVIEW_TRASH, "Close")), split_(new ActionButton(IDR_ATHENA_OVERVIEW_SPLIT, "Split")), current_action_(ACTION_TYPE_NONE), @@ -128,14 +129,17 @@ OverviewToolbar::~OverviewToolbar() { OverviewToolbar::ActionType OverviewToolbar::GetHighlightAction( const ui::GestureEvent& event) const { - if (IsEventOverButton(split_.get(), event)) + if (IsActionEnabled(ACTION_TYPE_SPLIT) && + IsEventOverButton(split_.get(), event)) return ACTION_TYPE_SPLIT; - if (IsEventOverButton(close_.get(), event)) + if (IsActionEnabled(ACTION_TYPE_CLOSE) && + IsEventOverButton(close_.get(), event)) return ACTION_TYPE_CLOSE; return ACTION_TYPE_NONE; } void OverviewToolbar::SetHighlightAction(ActionType action) { + CHECK(IsActionEnabled(action)); if (current_action_ == action) return; current_action_ = action; @@ -157,12 +161,21 @@ void OverviewToolbar::HideActionButtons() { ToggleActionButtonsVisibility(); } +void OverviewToolbar::DisableAction(ActionType action) { + CHECK_NE(current_action_, action); + disabled_action_bitfields_ |= (1u << action); +} + void OverviewToolbar::ToggleActionButtonsVisibility() { shown_ = !shown_; TransformButton(close_.get()); TransformButton(split_.get()); } +bool OverviewToolbar::IsActionEnabled(ActionType action) const { + return !(disabled_action_bitfields_ & (1u << action)); +} + bool OverviewToolbar::IsEventOverButton(ActionButton* button, const ui::GestureEvent& event) const { const int kBoundsInsetForTarget = 30; @@ -193,7 +206,10 @@ void OverviewToolbar::TransformButton(ActionButton* button) { button->layer()->GetAnimator()); split_settings.SetTweenType(gfx::Tween::SMOOTH_IN_OUT); button->layer()->SetTransform(ComputeTransformFor(button)); - button->layer()->SetOpacity(shown_ ? 1 : 0); + bool button_is_enabled = + (button == close_.get() && IsActionEnabled(ACTION_TYPE_CLOSE)) || + (button == split_.get() && IsActionEnabled(ACTION_TYPE_SPLIT)); + button->layer()->SetOpacity((button_is_enabled && shown_) ? 1 : 0); } } // namespace athena diff --git a/athena/wm/overview_toolbar.h b/athena/wm/overview_toolbar.h index a6fdb3b..937c35a 100644 --- a/athena/wm/overview_toolbar.h +++ b/athena/wm/overview_toolbar.h @@ -47,14 +47,18 @@ class OverviewToolbar { void ShowActionButtons(); void HideActionButtons(); + void DisableAction(ActionType action); + private: void ToggleActionButtonsVisibility(); + bool IsActionEnabled(ActionType action) const; bool IsEventOverButton(ActionButton* button, const ui::GestureEvent& event) const; gfx::Transform ComputeTransformFor(ActionButton* button) const; void TransformButton(ActionButton* button); bool shown_; + uint64_t disabled_action_bitfields_; scoped_ptr<ActionButton> close_; scoped_ptr<ActionButton> split_; ActionType current_action_; diff --git a/athena/wm/window_overview_mode.cc b/athena/wm/window_overview_mode.cc index 8b6bb04..fbf4342 100644 --- a/athena/wm/window_overview_mode.cc +++ b/athena/wm/window_overview_mode.cc @@ -98,6 +98,32 @@ void RestoreWindowState(aura::Window* window, wm::SetShadowType(window, wm::SHADOW_TYPE_NONE); } +gfx::RectF GetTransformedBounds(aura::Window* window) { + gfx::Transform transform; + gfx::RectF bounds = window->bounds(); + transform.Translate(bounds.x(), bounds.y()); + transform.PreconcatTransform(window->layer()->transform()); + transform.Translate(-bounds.x(), -bounds.y()); + transform.TransformRect(&bounds); + return bounds; +} + +gfx::Transform GetTransformForSplitWindow(aura::Window* window, float scale) { + int x_translate = window->bounds().width() * (1 - scale) / 2; + gfx::Transform transform; + transform.Translate(x_translate, window->bounds().height() * 0.65); + transform.Scale(scale, scale); + return transform; +} + +void TransformSplitWindowScale(aura::Window* window, float scale) { + gfx::Transform transform = window->layer()->GetTargetTransform(); + if (transform.Scale2d() == gfx::Vector2dF(scale, scale)) + return; + ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); + window->SetTransform(GetTransformForSplitWindow(window, scale)); +} + // Always returns the same target. class StaticWindowTargeter : public aura::WindowTargeter { public: @@ -178,9 +204,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode, (window == split_view_controller_->left_window() || window == split_view_controller_->right_window())) { // Do not let the left/right windows be scrolled. - int x_translate = window->bounds().width() * (1 - kMaxScale) / 2; - state->top.Translate(x_translate, window->bounds().height() * 0.65); - state->top.Scale(kMaxScale, kMaxScale); + state->top = GetTransformForSplitWindow(window, kMaxScale); state->bottom = state->top; --index; continue; @@ -347,6 +371,21 @@ class WindowOverviewModeImpl : public WindowOverviewMode, compositor->RemoveAnimationObserver(this); } + aura::Window* GetSplitWindowDropTarget(const ui::GestureEvent& event) const { + if (!split_view_controller_->IsSplitViewModeActive()) + return NULL; + CHECK(dragged_window_); + CHECK_NE(split_view_controller_->left_window(), dragged_window_); + CHECK_NE(split_view_controller_->right_window(), dragged_window_); + aura::Window* window = split_view_controller_->left_window(); + if (GetTransformedBounds(window).Contains(event.location())) + return window; + window = split_view_controller_->right_window(); + if (GetTransformedBounds(window).Contains(event.location())) + return window; + return NULL; + } + void DragWindow(const ui::GestureEvent& event) { CHECK(dragged_window_); CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); @@ -384,6 +423,8 @@ class WindowOverviewModeImpl : public WindowOverviewMode, overview_toolbar_->current_action(); overview_toolbar_->SetHighlightAction(new_action); + aura::Window* split_drop = GetSplitWindowDropTarget(event); + // If the user has selected to get into split-view mode, then show the // window with full opacity. Otherwise, fade it out as it closes. Animate // the opacity if transitioning to/from the split-view button. @@ -394,7 +435,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode, float ratio = std::min( 1.f, std::abs(dragged_distance.x()) / kMinDistanceForDismissal); float opacity = - (new_action == OverviewToolbar::ACTION_TYPE_SPLIT) + (new_action == OverviewToolbar::ACTION_TYPE_SPLIT || split_drop) ? 1 : gfx::Tween::FloatValueBetween(ratio, kMaxOpacity, kMinOpacity); if (animate_opacity) { @@ -404,6 +445,18 @@ class WindowOverviewModeImpl : public WindowOverviewMode, } else { dragged_window_->layer()->SetOpacity(opacity); } + + if (split_view_controller_->IsSplitViewModeActive()) { + float scale = kMaxScale; + if (split_drop == split_view_controller_->left_window()) + scale = kMaxScaleForSplitTarget; + TransformSplitWindowScale(split_view_controller_->left_window(), scale); + + scale = kMaxScale; + if (split_drop == split_view_controller_->right_window()) + scale = kMaxScaleForSplitTarget; + TransformSplitWindowScale(split_view_controller_->right_window(), scale); + } } bool ShouldCloseDragWindow(const ui::GestureEvent& event) const { @@ -513,9 +566,26 @@ class WindowOverviewModeImpl : public WindowOverviewMode, CHECK(overview_toolbar_); OverviewToolbar::ActionType action = overview_toolbar_->current_action(); overview_toolbar_.reset(); - if (action == OverviewToolbar::ACTION_TYPE_SPLIT) + if (action == OverviewToolbar::ACTION_TYPE_SPLIT) { delegate_->OnSplitViewMode(NULL, dragged_window_); - else if (ShouldCloseDragWindow(gesture)) + return; + } + + // If the window is dropped on one of the left/right windows in split-mode, + // then switch that window. + aura::Window* split_drop = GetSplitWindowDropTarget(gesture); + if (split_drop) { + aura::Window* left = split_view_controller_->left_window(); + aura::Window* right = split_view_controller_->right_window(); + if (left == split_drop) + left = dragged_window_; + else + right = dragged_window_; + delegate_->OnSplitViewMode(left, right); + return; + } + + if (ShouldCloseDragWindow(gesture)) CloseDragWindow(gesture); else RestoreDragWindow(); @@ -567,8 +637,26 @@ class WindowOverviewModeImpl : public WindowOverviewMode, std::abs(gesture->details().scroll_y_hint()) * 2) { dragged_start_location_ = gesture->location(); dragged_window_ = SelectWindowAt(gesture); - if (dragged_window_) + if (split_view_controller_->IsSplitViewModeActive() && + (dragged_window_ == split_view_controller_->left_window() || + dragged_window_ == split_view_controller_->right_window())) { + // TODO(sad): Allow closing the left/right window. Closing one of + // these windows will terminate the split-view mode. Until then, do + // not allow closing these (since otherwise it gets into an undefined + // state). + dragged_window_ = NULL; + } + + if (dragged_window_) { + // Show the toolbar (for closing a window, or going into split-view + // mode). If already in split-view mode, then do not show the 'Split' + // option. overview_toolbar_.reset(new OverviewToolbar(container_)); + if (split_view_controller_->IsSplitViewModeActive()) { + overview_toolbar_->DisableAction( + OverviewToolbar::ACTION_TYPE_SPLIT); + } + } } } else if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { if (dragged_window_) @@ -617,6 +705,7 @@ class WindowOverviewModeImpl : public WindowOverviewMode, const float kMaxScale = 0.75f; const float kMaxOpacity = 1.0f; const float kMinOpacity = 0.2f; + const float kMaxScaleForSplitTarget = 0.9f; aura::Window* container_; // Provider of the stack of windows to show in the overview mode. Not owned. |