• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/wm/gestures/tray_gesture_handler.h"
6 
7 #include "ash/shell.h"
8 #include "ash/system/tray/system_tray.h"
9 #include "ash/system/tray/system_tray_bubble.h"
10 #include "ui/aura/window.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/events/event.h"
13 #include "ui/gfx/transform.h"
14 #include "ui/views/widget/widget.h"
15 
16 const int kMinBubbleHeight = 13;
17 
18 namespace ash {
19 
TrayGestureHandler()20 TrayGestureHandler::TrayGestureHandler()
21     : widget_(NULL),
22       gesture_drag_amount_(0) {
23   // TODO(oshima): Support multiple display case.
24   SystemTray* tray = Shell::GetInstance()->GetPrimarySystemTray();
25   tray->ShowDefaultView(BUBBLE_CREATE_NEW);
26   SystemTrayBubble* bubble = tray->GetSystemBubble();
27   if (!bubble)
28     return;
29   bubble->bubble_view()->set_gesture_dragging(true);
30   widget_ = bubble->bubble_view()->GetWidget();
31   widget_->AddObserver(this);
32 
33   gfx::Rect bounds = widget_->GetWindowBoundsInScreen();
34   int height_change = bounds.height() - kMinBubbleHeight;
35   bounds.set_height(kMinBubbleHeight);
36   bounds.set_y(bounds.y() + height_change);
37   widget_->SetBounds(bounds);
38 }
39 
~TrayGestureHandler()40 TrayGestureHandler::~TrayGestureHandler() {
41   if (widget_)
42     widget_->RemoveObserver(this);
43 }
44 
UpdateGestureDrag(const ui::GestureEvent & event)45 bool TrayGestureHandler::UpdateGestureDrag(const ui::GestureEvent& event) {
46   CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type());
47   if (!widget_)
48     return false;
49 
50   gesture_drag_amount_ += event.details().scroll_y();
51   if (gesture_drag_amount_ > 0 && gesture_drag_amount_ < kMinBubbleHeight) {
52     widget_->Close();
53     return false;
54   }
55 
56   gfx::Rect bounds = widget_->GetWindowBoundsInScreen();
57   int new_height = std::min(
58       kMinBubbleHeight + std::max(0, static_cast<int>(-gesture_drag_amount_)),
59       widget_->GetContentsView()->GetPreferredSize().height());
60   int height_change = bounds.height() - new_height;
61   bounds.set_height(new_height);
62   bounds.set_y(bounds.y() + height_change);
63   widget_->SetBounds(bounds);
64   return true;
65 }
66 
CompleteGestureDrag(const ui::GestureEvent & event)67 void TrayGestureHandler::CompleteGestureDrag(const ui::GestureEvent& event) {
68   if (!widget_)
69     return;
70 
71   widget_->RemoveObserver(this);
72 
73   // Close the widget if it hasn't been dragged enough.
74   bool should_close = false;
75   int height = widget_->GetWindowBoundsInScreen().height();
76   int preferred_height =
77       widget_->GetContentsView()->GetPreferredSize().height();
78   if (event.type() == ui::ET_GESTURE_SCROLL_END) {
79     const float kMinThresholdGestureDrag = 0.4f;
80     if (height < preferred_height * kMinThresholdGestureDrag)
81       should_close = true;
82   } else if (event.type() == ui::ET_SCROLL_FLING_START) {
83     const float kMinThresholdGestureDragExposeFling = 0.25f;
84     const float kMinThresholdGestureFling = 1000.f;
85     if (height < preferred_height * kMinThresholdGestureDragExposeFling &&
86         event.details().velocity_y() > -kMinThresholdGestureFling)
87       should_close = true;
88   } else {
89     NOTREACHED();
90   }
91 
92   if (should_close) {
93     widget_->Close();
94   } else {
95     SystemTrayBubble* bubble =
96         Shell::GetInstance()->GetPrimarySystemTray()->GetSystemBubble();
97     if (bubble)
98       bubble->bubble_view()->set_gesture_dragging(false);
99   }
100 }
101 
OnWidgetDestroying(views::Widget * widget)102 void TrayGestureHandler::OnWidgetDestroying(views::Widget* widget) {
103   CHECK_EQ(widget_, widget);
104   widget_ = NULL;
105 }
106 
107 }  // namespace ash
108