summaryrefslogtreecommitdiffstats
path: root/athena
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-12 01:33:46 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-12 01:33:46 +0000
commit43e261198eb1311af3e6147f1de8883938ba869c (patch)
treeaa3aadadf0d265bea0000efb597ccf041bd5e848 /athena
parent4a00447f2c72f8716ba3daa953a49546ba674aaa (diff)
downloadchromium_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/DEPS1
-rw-r--r--athena/activity/activity_frame_view.cc5
-rw-r--r--athena/athena.gyp4
-rw-r--r--athena/common/DEPS1
-rw-r--r--athena/common/closure_animation_observer.cc22
-rw-r--r--athena/common/closure_animation_observer.h32
-rw-r--r--athena/wm/DEPS2
-rw-r--r--athena/wm/title_drag_controller.cc144
-rw-r--r--athena/wm/title_drag_controller.h66
-rw-r--r--athena/wm/window_manager_impl.cc36
-rw-r--r--athena/wm/window_overview_mode.cc24
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*)