summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--athena/wm/overview_toolbar.cc22
-rw-r--r--athena/wm/overview_toolbar.h4
-rw-r--r--athena/wm/window_overview_mode.cc103
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.