// Copyright (c) 2012 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 "ash/wm/gestures/tray_gesture_handler.h" #include "ash/shell.h" #include "ash/system/tray/system_tray.h" #include "ash/system/tray/system_tray_bubble.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" #include "ui/events/event.h" #include "ui/gfx/transform.h" #include "ui/views/widget/widget.h" const int kMinBubbleHeight = 13; namespace ash { namespace internal { TrayGestureHandler::TrayGestureHandler() : widget_(NULL), gesture_drag_amount_(0) { // TODO(oshima): Support multiple display case. SystemTray* tray = Shell::GetInstance()->GetPrimarySystemTray(); tray->ShowDefaultView(BUBBLE_CREATE_NEW); SystemTrayBubble* bubble = tray->GetSystemBubble(); if (!bubble) return; bubble->bubble_view()->set_gesture_dragging(true); widget_ = bubble->bubble_view()->GetWidget(); widget_->AddObserver(this); gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); int height_change = bounds.height() - kMinBubbleHeight; bounds.set_height(kMinBubbleHeight); bounds.set_y(bounds.y() + height_change); widget_->SetBounds(bounds); } TrayGestureHandler::~TrayGestureHandler() { if (widget_) widget_->RemoveObserver(this); } bool TrayGestureHandler::UpdateGestureDrag(const ui::GestureEvent& event) { CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); if (!widget_) return false; gesture_drag_amount_ += event.details().scroll_y(); if (gesture_drag_amount_ > 0 && gesture_drag_amount_ < kMinBubbleHeight) { widget_->Close(); return false; } gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); int new_height = std::min( kMinBubbleHeight + std::max(0, static_cast(-gesture_drag_amount_)), widget_->GetContentsView()->GetPreferredSize().height()); int height_change = bounds.height() - new_height; bounds.set_height(new_height); bounds.set_y(bounds.y() + height_change); widget_->SetBounds(bounds); return true; } void TrayGestureHandler::CompleteGestureDrag(const ui::GestureEvent& event) { if (!widget_) return; widget_->RemoveObserver(this); // Close the widget if it hasn't been dragged enough. bool should_close = false; int height = widget_->GetWindowBoundsInScreen().height(); int preferred_height = widget_->GetContentsView()->GetPreferredSize().height(); if (event.type() == ui::ET_GESTURE_SCROLL_END) { const float kMinThresholdGestureDrag = 0.4f; if (height < preferred_height * kMinThresholdGestureDrag) should_close = true; } else if (event.type() == ui::ET_SCROLL_FLING_START) { const float kMinThresholdGestureDragExposeFling = 0.25f; const float kMinThresholdGestureFling = 1000.f; if (height < preferred_height * kMinThresholdGestureDragExposeFling && event.details().velocity_y() > -kMinThresholdGestureFling) should_close = true; } else { NOTREACHED(); } if (should_close) { widget_->Close(); } else { SystemTrayBubble* bubble = Shell::GetInstance()->GetPrimarySystemTray()->GetSystemBubble(); if (bubble) bubble->bubble_view()->set_gesture_dragging(false); } } void TrayGestureHandler::OnWidgetDestroying(views::Widget* widget) { CHECK_EQ(widget_, widget); widget_ = NULL; } } // namespace internal } // namespace ash