summaryrefslogtreecommitdiff
path: root/chromium/ash/wm/gestures/tray_gesture_handler.cc
blob: 78b0fb308c85e66764b2f33afa5a12d9d0c76c94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// 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/base/events/event.h"
#include "ui/compositor/layer.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<int>(-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