Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3877)

Unified Diff: athena/wm/split_view_controller.cc

Issue 420603011: Split Screen mode implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@split_view
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: athena/wm/split_view_controller.cc
diff --git a/athena/wm/split_view_controller.cc b/athena/wm/split_view_controller.cc
index 7da36755f7e76433545753ba21a2e4c1f89f3b02..c35c233758edbc5bd900607f94128b76f04dd359 100644
--- a/athena/wm/split_view_controller.cc
+++ b/athena/wm/split_view_controller.cc
@@ -4,29 +4,274 @@
#include "athena/wm/split_view_controller.h"
+#include "athena/common/drag_handle.h"
+#include "athena/wm/public/window_manager.h"
+#include "athena/wm/window_stack_provider.h"
+#include "base/bind.h"
#include "ui/aura/window.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event_handler.h"
namespace athena {
+namespace {
-SplitViewController::SplitViewController() {
+// An animation observer that runs a callback at the end of the animation, and
+// destroys itself.
+class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
+ public:
+ CallbackAnimationObserver(const base::Closure& closure)
+ : closure_(closure) {
+ }
+
+ virtual ~CallbackAnimationObserver() {}
+
+ private:
+ // Overridden from ui::ImplicitAnimationObserver:
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ if (!closure_.is_null())
+ closure_.Run();
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
oshima 2014/07/25 21:41:10 can't you remove immediately?
mfomitchev 2014/08/05 19:56:57 Yup, looks like I can. I think this used to cause
+ }
+
+ const base::Closure closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
+};
+
+} // namespace
+
+SplitViewController::SplitViewController(
+ aura::Window* container,
+ WindowStackProvider* window_stack_provider,
+ WindowManager* window_manager)
+ : weak_factory_(this),
+ state_(INACTIVE),
+ container_(container),
+ window_manager_(window_manager),
+ window_stack_provider_(window_stack_provider),
+ current_window_(NULL),
+ left_window_(NULL),
+ right_window_(NULL),
+ separator_position_(0) {
+ window_manager->AddObserver(this);
}
SplitViewController::~SplitViewController() {
}
+bool SplitViewController::IsSplitViewModeActive() {
+ return state_ == ACTIVE;
+}
+
+void SplitViewController::Layout(bool animate) {
+ if (left_window_) {
+ CHECK(right_window_);
+ gfx::Transform left_transform;
+ gfx::Transform right_transform;
+ int container_width = container_->GetBoundsInScreen().width();
+ if (state_ == ACTIVE) {
+ left_transform.Scale(.5, 1);
+ right_transform.Scale(.5, 1);
+ right_transform.Translate(container_width, 0);
+ } else {
+ left_transform.Translate(separator_position_ - container_width, 0);
+ right_transform.Translate(separator_position_, 0);
+ }
+ left_window_->Show();
+ right_window_->Show();
+ SetWindowTransform(left_window_, left_transform, animate);
+ SetWindowTransform(right_window_, right_transform, animate);
+ }
+}
+
+void SplitViewController::SetWindowTransform(
+ aura::Window* window, const gfx::Transform& transform, bool animate) {
+ if (animate) {
+ scoped_refptr<ui::LayerAnimator> animator =
+ window->layer()->GetAnimator();
+ ui::ScopedLayerAnimationSettings settings(animator);
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.AddObserver(new CallbackAnimationObserver(
+ base::Bind(&SplitViewController::AnimationCompleted,
+ weak_factory_.GetWeakPtr())));
+ //settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(250));
+ window->SetTransform(transform);
+
+ // TODO: In the end of the animation we need to hide the window that's off
+ // screen and also set transforms for all windows to gfx::Transform
+ // (for the case where one window is animated off screen).
+ } else {
+ window->SetTransform(transform);
+ }
+}
+
+void SplitViewController::AnimationCompleted() {
+ LOG(ERROR) << "AnimationCompleted";
+ if (state_ == ACTIVE) {
+ gfx::Rect bounds_size = gfx::Rect(container_->GetBoundsInScreen().size());
+ int container_width = bounds_size.width();
+ bounds_size.set_width(container_width / 2);
+ left_window_->SetBounds(bounds_size);
+ left_window_->SetTransform(gfx::Transform());
+ right_window_->SetBounds(bounds_size);
+ gfx::Transform right_transform;
+ right_transform.Translate(container_width / 2, 0);
+ right_window_->SetTransform(right_transform);
+ } else {
+ int container_width = container_->GetBoundsInScreen().width();
+ left_window_->SetTransform(gfx::Transform());
+ right_window_->SetTransform(gfx::Transform());
+ if (separator_position_ == 0)
+ left_window_->Hide();
+ else if (separator_position_ == container_width)
+ right_window_->Hide();
+ }
+}
+
+void SplitViewController::UpdateSeparatorPositionFromScrollDelta(float delta) {
+ int container_width = container_->GetBoundsInScreen().width();
+ separator_position_ = delta > 0 ? (int) delta : container_width + delta;
+}
+
+aura::Window* SplitViewController::GetCurrentWindow() {
+ const aura::Window::Windows& windows =
+ window_stack_provider_->GetWindowStack();
+
+ LOG(ERROR) << "GetCurrentWindow: current_window_=" << current_window_;
+ LOG(ERROR) << "All Windows:";
+ int i = 0;
+ aura::Window::Windows::const_iterator it;
+ for (it = windows.begin(); it != windows.end(); ++it) {
+ LOG(ERROR) << " Window " << i << ": " << *it;
+ ++i;
+ }
+
+ if (windows.empty())
+ return NULL;
+ if (!current_window_)
+ current_window_ = windows.back();
+ return current_window_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Begin BezelController::ScrollDelegate overrides.
void SplitViewController::ScrollBegin(BezelController::Bezel bezel,
float delta) {
+ LOG(ERROR) << "ScrollBegin";
+ if (!CanScroll())
+ return;
+ state_ = SCROLLING;
+ aura::Window* current_window = GetCurrentWindow();
+ CHECK(current_window);
+
+ const aura::Window::Windows& windows =
+ window_stack_provider_->GetWindowStack();
+ CHECK(windows.size() >= 2);
+ aura::Window::Windows::const_iterator it = std::find(
+ windows.begin(), windows.end(), current_window);
+ CHECK(it != windows.end());
+
+ if (delta > 0) {
+ right_window_ = current_window;
+ // reverse iterator points to the position before normal iterator |it|
+ aura::Window::Windows::const_reverse_iterator rev_it(it);
+ // circle to end if needed.
+ left_window_ = rev_it == windows.rend() ? windows.back() : *(rev_it);
+ } else {
+ left_window_ = current_window;
+ ++it;
+ // circle to front if needed.
+ right_window_ = it == windows.end() ? windows.front() : *it;
+ }
+
+ CHECK(left_window_);
+ CHECK(right_window_);
+
+ // HACK until we are properly hiding windows in window manager
+ // Loop through all windows and hide them
+ for (it = windows.begin(); it != windows.end(); ++it) {
+ if (*it != left_window_ && *it != right_window_)
+ (*it)->Hide();
+ }
+
+ LOG(ERROR) << "left_window_=" << left_window_
+ << ", right_window_=" << right_window_;
+
+ // END HACK
+/*
+ it = std::find(windows.begin(), windows.end(), left_window_);
+ size_t index_left = std::distance(windows.begin(), it);
+ it = std::find(windows.begin(), windows.end(), right_window_);
+ size_t index_right = std::distance(windows.begin(), it);
+ LOG(ERROR) << "IndexLeft=" << index_left
+ << ", IndexRight=" << index_right;
+*/
+
+ UpdateSeparatorPositionFromScrollDelta(delta);
+ Layout(false);
}
+// Max distance from the scroll end position to the middle of the screen where
+// we would go into the split view mode.
+const int kMaxDistanceFromMiddle = 120;
void SplitViewController::ScrollEnd() {
+ LOG(ERROR) << "ScrollEnd";
+ if (state_ != SCROLLING)
+ return;
+
+ int cont_width = container_->GetBoundsInScreen().width();
+ if (abs(cont_width / 2 - separator_position_) <= kMaxDistanceFromMiddle) {
+ state_ = ACTIVE;
+ separator_position_ = cont_width / 2;
+ LOG(ERROR) << "Entering split view mode!";
+ } else if (separator_position_ < cont_width / 2) {
+ separator_position_ = 0;
+ current_window_ = right_window_;
+ state_ = INACTIVE;
+ } else {
+ separator_position_ = cont_width;
+ current_window_ = left_window_;
+ state_ = INACTIVE;
+ }
+ Layout(true);
}
void SplitViewController::ScrollUpdate(float delta) {
+ if (state_ != SCROLLING)
+ return;
+ UpdateSeparatorPositionFromScrollDelta(delta);
+ Layout(false);
}
bool SplitViewController::CanScroll() {
- return false;
+ // TODO (mfomitchev): return false in vertical orientation, in full screen.
+ bool result = (!window_manager_->IsOverviewModeActive() &&
+ !IsSplitViewModeActive() &&
+ window_stack_provider_->GetWindowStack().size() >= 2);
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowManagerObserver overrides
+void SplitViewController::OnOverviewModeEnter() {
+ if (state_ == ACTIVE) {
+ CHECK(left_window_);
+ CHECK(right_window_);
+ window_stack_provider_->MoveWindowToFront(right_window_);
+ window_stack_provider_->MoveWindowToFront(left_window_);
+ // TODO (mfomitchev): This shouldn't be done here, but the overview mode's
+ // transition animation currently looks bad if the starting transform of
+ // any window is not gfx::Transform().
+ right_window_->SetTransform(gfx::Transform());
+ } else if (current_window_) {
+ window_stack_provider_->MoveWindowToFront(current_window_);
+ }
+ current_window_ = NULL;
+ left_window_ = NULL;
+ right_window_ = NULL;
+ state_ = INACTIVE;
}
} // namespace athena

Powered by Google App Engine
This is Rietveld 408576698