diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 01:33:46 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-12 01:33:46 +0000 |
commit | 43e261198eb1311af3e6147f1de8883938ba869c (patch) | |
tree | aa3aadadf0d265bea0000efb597ccf041bd5e848 /athena | |
parent | 4a00447f2c72f8716ba3daa953a49546ba674aaa (diff) | |
download | chromium_src-43e261198eb1311af3e6147f1de8883938ba869c.zip chromium_src-43e261198eb1311af3e6147f1de8883938ba869c.tar.gz chromium_src-43e261198eb1311af3e6147f1de8883938ba869c.tar.bz2 |
athena: Allow dragging the window-title down to switch between windows.
BUG=397272
R=mukai@chromium.org, oshima@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/456093002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288865 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'athena')
-rw-r--r-- | athena/activity/DEPS | 1 | ||||
-rw-r--r-- | athena/activity/activity_frame_view.cc | 5 | ||||
-rw-r--r-- | athena/athena.gyp | 4 | ||||
-rw-r--r-- | athena/common/DEPS | 1 | ||||
-rw-r--r-- | athena/common/closure_animation_observer.cc | 22 | ||||
-rw-r--r-- | athena/common/closure_animation_observer.h | 32 | ||||
-rw-r--r-- | athena/wm/DEPS | 2 | ||||
-rw-r--r-- | athena/wm/title_drag_controller.cc | 144 | ||||
-rw-r--r-- | athena/wm/title_drag_controller.h | 66 | ||||
-rw-r--r-- | athena/wm/window_manager_impl.cc | 36 | ||||
-rw-r--r-- | athena/wm/window_overview_mode.cc | 24 |
11 files changed, 313 insertions, 24 deletions
diff --git a/athena/activity/DEPS b/athena/activity/DEPS index aafc6d4..78a4371 100644 --- a/athena/activity/DEPS +++ b/athena/activity/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+athena/screen", "+ui/aura", + "+ui/base", "+ui/views", ] diff --git a/athena/activity/activity_frame_view.cc b/athena/activity/activity_frame_view.cc index 3f1260b..ca2e8be 100644 --- a/athena/activity/activity_frame_view.cc +++ b/athena/activity/activity_frame_view.cc @@ -8,6 +8,7 @@ #include <vector> #include "athena/activity/public/activity_view_model.h" +#include "ui/base/hit_test.h" #include "ui/views/background.h" #include "ui/views/controls/label.h" #include "ui/views/view.h" @@ -53,6 +54,10 @@ gfx::Rect ActivityFrameView::GetWindowBoundsForClientBounds( } int ActivityFrameView::NonClientHitTest(const gfx::Point& point) { + if (frame_->IsFullscreen()) + return 0; + if (title_->bounds().Contains(point)) + return HTCAPTION; return 0; } diff --git a/athena/athena.gyp b/athena/athena.gyp index 4e2cdb2..3a4d359 100644 --- a/athena/athena.gyp +++ b/athena/athena.gyp @@ -38,6 +38,8 @@ 'activity/public/activity_view_manager.h', 'activity/public/activity_view_model.h', 'athena_export.h', + 'common/closure_animation_observer.cc', + 'common/closure_animation_observer.h', 'common/container_priorities.h', 'common/fill_layout_manager.cc', 'common/fill_layout_manager.h', @@ -73,6 +75,8 @@ 'wm/bezel_controller.h', 'wm/split_view_controller.cc', 'wm/split_view_controller.h', + 'wm/title_drag_controller.cc', + 'wm/title_drag_controller.h', 'wm/window_manager_impl.cc', 'wm/window_overview_mode.cc', 'wm/window_overview_mode.h', diff --git a/athena/common/DEPS b/athena/common/DEPS index 716fe60..8755565 100644 --- a/athena/common/DEPS +++ b/athena/common/DEPS @@ -1,4 +1,5 @@ include_rules = [ "+athena/athena_export.h", "+ui/aura", + "+ui/compositor", ] diff --git a/athena/common/closure_animation_observer.cc b/athena/common/closure_animation_observer.cc new file mode 100644 index 0000000..083aec0 --- /dev/null +++ b/athena/common/closure_animation_observer.cc @@ -0,0 +1,22 @@ +// Copyright 2014 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 "athena/common/closure_animation_observer.h" + +namespace athena { + +ClosureAnimationObserver::ClosureAnimationObserver(const base::Closure& closure) + : closure_(closure) { + DCHECK(!closure_.is_null()); +} + +ClosureAnimationObserver::~ClosureAnimationObserver() { +} + +void ClosureAnimationObserver::OnImplicitAnimationsCompleted() { + closure_.Run(); + delete this; +} + +} // namespace athena diff --git a/athena/common/closure_animation_observer.h b/athena/common/closure_animation_observer.h new file mode 100644 index 0000000..50e0ec8 --- /dev/null +++ b/athena/common/closure_animation_observer.h @@ -0,0 +1,32 @@ +// Copyright 2014 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 ATHENA_COMMON_CLOSURE_ANIMATION_OBSERVER_H_ +#define ATHENA_COMMON_CLOSURE_ANIMATION_OBSERVER_H_ + +#include "base/callback.h" +#include "base/macros.h" +#include "ui/compositor/layer_animation_observer.h" + +namespace athena { + +// Runs a callback at the end of the animation. This observe also destroys +// itself afterwards. +class ClosureAnimationObserver : public ui::ImplicitAnimationObserver { + public: + explicit ClosureAnimationObserver(const base::Closure& closure); + + private: + virtual ~ClosureAnimationObserver(); + + // ui::ImplicitAnimationObserver: + virtual void OnImplicitAnimationsCompleted() OVERRIDE; + + const base::Closure closure_; + + DISALLOW_COPY_AND_ASSIGN(ClosureAnimationObserver); +}; +} + +#endif // ATHENA_COMMON_CLOSURE_ANIMATION_OBSERVER_H_ diff --git a/athena/wm/DEPS b/athena/wm/DEPS index f24508c..a3cece5 100644 --- a/athena/wm/DEPS +++ b/athena/wm/DEPS @@ -1,7 +1,9 @@ include_rules = [ + "+athena/common", "+athena/input/public", "+athena/screen/public", "+ui/aura", + "+ui/base", "+ui/compositor", "+ui/events", "+ui/gfx", diff --git a/athena/wm/title_drag_controller.cc b/athena/wm/title_drag_controller.cc new file mode 100644 index 0000000..597f50a --- /dev/null +++ b/athena/wm/title_drag_controller.cc @@ -0,0 +1,144 @@ +// Copyright 2014 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 "athena/wm/title_drag_controller.h" + +#include "athena/common/closure_animation_observer.h" +#include "base/bind.h" +#include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" +#include "ui/base/hit_test.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/wm/core/shadow.h" +#include "ui/wm/core/window_util.h" + +namespace { + +// The minimum amount to drag to confirm a window switch at the end of the +// non-fling gesture. +const int kMinDragDistanceForSwitch = 300; +// The minimum velocity to confirm a window switch for a fling (only applicable +// if the amount dragged was not sufficient, i.e. smaller than +// kMinDragDistanceForSwitch). +const int kMinDragVelocityForSwitch = 5000; + +} + +namespace athena { + +TitleDragController::TitleDragController(aura::Window* container, + TitleDragControllerDelegate* delegate) + : container_(container), + delegate_(delegate), + weak_ptr_(this) { + CHECK(container_); + CHECK(delegate_); + container_->AddPreTargetHandler(this); +} + +TitleDragController::~TitleDragController() { + container_->RemovePreTargetHandler(this); +} + +void TitleDragController::EndTransition(aura::Window* window, bool complete) { + ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); + settings.SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + settings.AddObserver(new ClosureAnimationObserver( + base::Bind(&TitleDragController::OnTransitionEnd, + weak_ptr_.GetWeakPtr(), + window, + complete))); + gfx::Transform transform; + transform.Translate(0, complete ? window->bounds().height() : 0); + window->SetTransform(transform); +} + +void TitleDragController::OnTransitionEnd(aura::Window* window, bool complete) { + weak_ptr_.InvalidateWeakPtrs(); + if (!tracker_.Contains(window)) + window = NULL; + if (complete && window && wm::IsActiveWindow(window)) + delegate_->OnTitleDragCompleted(window); + else + delegate_->OnTitleDragCanceled(window); + shadow_.reset(); + if (window) { + window->SetTransform(gfx::Transform()); + tracker_.Remove(window); + } +} + +void TitleDragController::OnGestureEvent(ui::GestureEvent* gesture) { + // Do not process any gesture events if an animation is still in progress from + // a previous drag. + if (weak_ptr_.HasWeakPtrs()) + return; + + if (gesture->type() == ui::ET_GESTURE_TAP_DOWN) { + // It is possible to start a gesture sequence on a second window while a + // drag is already in progress (e.g. the user starts interacting with the + // window that is being revealed by the title-drag). Ignore these gesture + // sequences. + if (!tracker_.windows().empty()) + return; + aura::Window* window = static_cast<aura::Window*>(gesture->target()); + if (!window || !window->delegate()) + return; + int component = + window->delegate()->GetNonClientComponent(gesture->location()); + if (component != HTCAPTION) + return; + if (!delegate_->GetWindowBehind(window)) + return; + tracker_.Add(window); + drag_start_location_ = gesture->root_location(); + return; + } + + // If this gesture is for a different window, then ignore. + aura::Window* window = static_cast<aura::Window*>(gesture->target()); + if (!tracker_.Contains(window)) + return; + + if (gesture->type() == ui::ET_GESTURE_SCROLL_BEGIN) { + delegate_->OnTitleDragStarted(window); + shadow_.reset(new wm::Shadow()); + shadow_->Init(wm::Shadow::STYLE_ACTIVE); + shadow_->SetContentBounds(gfx::Rect(window->bounds().size())); + window->layer()->Add(shadow_->layer()); + gesture->SetHandled(); + return; + } + + if (gesture->type() == ui::ET_GESTURE_SCROLL_UPDATE) { + gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; + gfx::Transform transform; + transform.Translate(0, std::max(0.f, distance.y())); + window->SetTransform(transform); + gesture->SetHandled(); + return; + } + + if (gesture->type() == ui::ET_GESTURE_SCROLL_END) { + gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; + EndTransition(window, distance.y() >= kMinDragDistanceForSwitch); + gesture->SetHandled(); + return; + } + + if (gesture->type() == ui::ET_SCROLL_FLING_START) { + gfx::Vector2dF distance = gesture->root_location() - drag_start_location_; + bool swipe_downwards = gesture->details().velocity_y() > 0; + EndTransition( + window, + swipe_downwards && + (distance.y() >= kMinDragDistanceForSwitch || + gesture->details().velocity_y() >= kMinDragVelocityForSwitch)); + gesture->SetHandled(); + } +} + +} // namespace athena diff --git a/athena/wm/title_drag_controller.h b/athena/wm/title_drag_controller.h new file mode 100644 index 0000000..1b4b2e5 --- /dev/null +++ b/athena/wm/title_drag_controller.h @@ -0,0 +1,66 @@ +// Copyright 2014 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 ATHENA_WM_TITLE_DRAG_CONTROLLER_H_ +#define ATHENA_WM_TITLE_DRAG_CONTROLLER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "ui/aura/window_tracker.h" +#include "ui/events/event_handler.h" +#include "ui/gfx/geometry/point.h" + +namespace aura { +class Window; +} + +namespace wm { +class Shadow; +} + +namespace athena { + +class TitleDragControllerDelegate { + public: + virtual ~TitleDragControllerDelegate() {} + + // Returns the window behind |window|. The returned window is the one that + // would be revealed while |window|'s title is dragged. + virtual aura::Window* GetWindowBehind(aura::Window* window) = 0; + + // Notifies the delegate during various stages of the drag. + virtual void OnTitleDragStarted(aura::Window* window) = 0; + virtual void OnTitleDragCompleted(aura::Window* window) = 0; + virtual void OnTitleDragCanceled(aura::Window* window) = 0; +}; + +// Responsible for allowing dragging a window by its title bar. +class TitleDragController : public ui::EventHandler { + public: + TitleDragController(aura::Window* container, + TitleDragControllerDelegate* delegate); + virtual ~TitleDragController(); + + private: + void EndTransition(aura::Window* window, bool complete); + void OnTransitionEnd(aura::Window* window, bool complete); + + // ui::EventHandler: + virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE; + + aura::Window* container_; + TitleDragControllerDelegate* delegate_; + gfx::Point drag_start_location_; + scoped_ptr<wm::Shadow> shadow_; + aura::WindowTracker tracker_; + + base::WeakPtrFactory<TitleDragController> weak_ptr_; + + DISALLOW_COPY_AND_ASSIGN(TitleDragController); +}; + +} // namespace athena + +#endif // ATHENA_WM_TITLE_DRAG_CONTROLLER_H_ diff --git a/athena/wm/window_manager_impl.cc b/athena/wm/window_manager_impl.cc index fb06188..e7cd444 100644 --- a/athena/wm/window_manager_impl.cc +++ b/athena/wm/window_manager_impl.cc @@ -4,12 +4,15 @@ #include "athena/wm/public/window_manager.h" +#include <algorithm> + #include "athena/common/container_priorities.h" #include "athena/input/public/accelerator_manager.h" #include "athena/screen/public/screen_manager.h" #include "athena/wm/bezel_controller.h" #include "athena/wm/public/window_manager_observer.h" #include "athena/wm/split_view_controller.h" +#include "athena/wm/title_drag_controller.h" #include "athena/wm/window_overview_mode.h" #include "base/logging.h" #include "base/observer_list.h" @@ -25,7 +28,8 @@ namespace { class WindowManagerImpl : public WindowManager, public WindowOverviewModeDelegate, public aura::WindowObserver, - public AcceleratorHandler { + public AcceleratorHandler, + public TitleDragControllerDelegate { public: WindowManagerImpl(); virtual ~WindowManagerImpl(); @@ -61,11 +65,18 @@ class WindowManagerImpl : public WindowManager, virtual bool OnAcceleratorFired(int command_id, const ui::Accelerator& accelerator) OVERRIDE; + // TitleDragControllerDelegate: + virtual aura::Window* GetWindowBehind(aura::Window* window) OVERRIDE; + virtual void OnTitleDragStarted(aura::Window* window) OVERRIDE; + virtual void OnTitleDragCompleted(aura::Window* window) OVERRIDE; + virtual void OnTitleDragCanceled(aura::Window* window) OVERRIDE; + scoped_ptr<aura::Window> container_; scoped_ptr<WindowOverviewMode> overview_; scoped_ptr<BezelController> bezel_controller_; scoped_ptr<SplitViewController> split_view_controller_; scoped_ptr<wm::WMState> wm_state_; + scoped_ptr<TitleDragController> title_drag_controller_; ObserverList<WindowManagerObserver> observers_; DISALLOW_COPY_AND_ASSIGN(WindowManagerImpl); @@ -102,6 +113,7 @@ WindowManagerImpl::WindowManagerImpl() { split_view_controller_.reset(new SplitViewController()); bezel_controller_->set_left_right_delegate(split_view_controller_.get()); container_->AddPreTargetHandler(bezel_controller_.get()); + title_drag_controller_.reset(new TitleDragController(container_.get(), this)); wm_state_.reset(new wm::WMState()); instance = this; InstallAccelerators(); @@ -113,6 +125,8 @@ WindowManagerImpl::~WindowManagerImpl() { container_->RemoveObserver(this); container_->RemovePreTargetHandler(bezel_controller_.get()); } + // |title_drag_controller_| needs to be reset before |container_|. + title_drag_controller_.reset(); container_.reset(); instance = NULL; } @@ -198,6 +212,26 @@ bool WindowManagerImpl::OnAcceleratorFired(int command_id, return true; } +aura::Window* WindowManagerImpl::GetWindowBehind(aura::Window* window) { + const aura::Window::Windows& windows = container_->children(); + aura::Window::Windows::const_iterator iter = + std::find(windows.begin(), windows.end(), window); + CHECK(iter != windows.end()); + return (iter == windows.begin()) ? NULL : *(iter - 1); +} + +void WindowManagerImpl::OnTitleDragStarted(aura::Window* window) { +} + +void WindowManagerImpl::OnTitleDragCompleted(aura::Window* window) { + aura::Window* next_window = GetWindowBehind(window); + if (next_window) + OnSelectWindow(next_window); +} + +void WindowManagerImpl::OnTitleDragCanceled(aura::Window* window) { +} + AthenaContainerLayoutManager::AthenaContainerLayoutManager() { } diff --git a/athena/wm/window_overview_mode.cc b/athena/wm/window_overview_mode.cc index e04858a..83f7003 100644 --- a/athena/wm/window_overview_mode.cc +++ b/athena/wm/window_overview_mode.cc @@ -8,6 +8,7 @@ #include <functional> #include <vector> +#include "athena/common/closure_animation_observer.h" #include "base/bind.h" #include "base/macros.h" #include "ui/aura/scoped_window_targeter.h" @@ -41,29 +42,6 @@ struct WindowOverviewState { scoped_ptr<wm::Shadow> shadow; }; -// Runs a callback at the end of the animation. This observe also destroys -// itself afterwards. -class ClosureAnimationObserver : public ui::ImplicitAnimationObserver { - public: - explicit ClosureAnimationObserver(const base::Closure& closure) - : closure_(closure) { - DCHECK(!closure_.is_null()); - } - private: - virtual ~ClosureAnimationObserver() { - } - - // ui::ImplicitAnimationObserver: - virtual void OnImplicitAnimationsCompleted() OVERRIDE { - closure_.Run(); - delete this; - } - - const base::Closure closure_; - - DISALLOW_COPY_AND_ASSIGN(ClosureAnimationObserver); -}; - } // namespace DECLARE_WINDOW_PROPERTY_TYPE(WindowOverviewState*) |