Home | History | Annotate | Download | only in gestures
      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 
     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 
     40 TrayGestureHandler::~TrayGestureHandler() {
     41   if (widget_)
     42     widget_->RemoveObserver(this);
     43 }
     44 
     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 
     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 
    102 void TrayGestureHandler::OnWidgetDestroying(views::Widget* widget) {
    103   CHECK_EQ(widget_, widget);
    104   widget_ = NULL;
    105 }
    106 
    107 }  // namespace ash
    108