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.
5 #include "ash/wm/gestures/system_pinch_handler.h"
7 #include "ash/launcher/launcher.h"
8 #include "ash/screen_ash.h"
9 #include "ash/shelf/shelf_widget.h"
10 #include "ash/shell.h"
11 #include "ash/wm/property_util.h"
12 #include "ash/wm/window_util.h"
13 #include "ash/wm/workspace/snap_sizer.h"
14 #include "ui/aura/window.h"
15 #include "ui/base/events/event_constants.h"
16 #include "ui/base/gestures/gesture_types.h"
17 #include "ui/compositor/scoped_layer_animation_settings.h"
18 #include "ui/gfx/rect.h"
19 #include "ui/views/widget/widget.h"
20 #include "ui/views/widget/widget_delegate.h"
22 const double kPinchThresholdForMaximize
= 1.5;
23 const double kPinchThresholdForMinimize
= 0.7;
28 const int SystemPinchHandler::kSystemGesturePoints
= 4;
30 SystemPinchHandler::SystemPinchHandler(aura::Window
* target
)
33 phantom_state_(PHANTOM_WINDOW_NORMAL
),
35 widget_
= views::Widget::GetWidgetForNativeWindow(target_
);
38 SystemPinchHandler::~SystemPinchHandler() {
41 SystemGestureStatus
SystemPinchHandler::ProcessGestureEvent(
42 const ui::GestureEvent
& event
) {
43 // The target has changed, somehow. Let's bale.
44 if (!widget_
|| !widget_
->widget_delegate()->CanResize())
45 return SYSTEM_GESTURE_END
;
47 switch (event
.type()) {
48 case ui::ET_GESTURE_END
: {
49 if (event
.details().touch_points() > kSystemGesturePoints
)
52 if (phantom_state_
== PHANTOM_WINDOW_MAXIMIZED
) {
53 if (!wm::IsWindowMaximized(target_
) &&
54 !wm::IsWindowFullscreen(target_
))
55 wm::MaximizeWindow(target_
);
56 } else if (phantom_state_
== PHANTOM_WINDOW_MINIMIZED
) {
57 if (wm::IsWindowMaximized(target_
) ||
58 wm::IsWindowFullscreen(target_
)) {
59 wm::RestoreWindow(target_
);
61 wm::MinimizeWindow(target_
);
63 // NOTE: Minimizing the window will cause this handler to be
64 // destroyed. So do not access anything from |this| from here.
65 return SYSTEM_GESTURE_END
;
68 return SYSTEM_GESTURE_END
;
71 case ui::ET_GESTURE_PINCH_UPDATE
: {
72 // The PINCH_UPDATE events contain incremental scaling updates.
73 pinch_factor_
*= event
.details().scale();
75 GetPhantomWindowScreenBounds(target_
, event
.location());
76 if (phantom_state_
!= PHANTOM_WINDOW_NORMAL
|| phantom_
.IsShowing())
77 phantom_
.Show(bounds
);
81 case ui::ET_GESTURE_MULTIFINGER_SWIPE
: {
84 phantom_state_
= PHANTOM_WINDOW_NORMAL
;
86 if (event
.details().swipe_left() || event
.details().swipe_right()) {
87 // Snap for left/right swipes.
88 ui::ScopedLayerAnimationSettings
settings(
89 target_
->layer()->GetAnimator());
90 internal::SnapSizer::SnapWindow(target_
,
91 event
.details().swipe_left() ? internal::SnapSizer::LEFT_EDGE
:
92 internal::SnapSizer::RIGHT_EDGE
);
93 } else if (event
.details().swipe_up()) {
94 if (!wm::IsWindowMaximized(target_
) &&
95 !wm::IsWindowFullscreen(target_
))
96 wm::MaximizeWindow(target_
);
97 } else if (event
.details().swipe_down()) {
98 wm::MinimizeWindow(target_
);
100 NOTREACHED() << "Swipe happened without a direction.";
109 return SYSTEM_GESTURE_PROCESSED
;
112 gfx::Rect
SystemPinchHandler::GetPhantomWindowScreenBounds(
113 aura::Window
* window
,
114 const gfx::Point
& point
) {
115 if (pinch_factor_
> kPinchThresholdForMaximize
) {
116 phantom_state_
= PHANTOM_WINDOW_MAXIMIZED
;
117 return ScreenAsh::ConvertRectToScreen(
119 ScreenAsh::GetMaximizedWindowBoundsInParent(target_
));
122 if (pinch_factor_
< kPinchThresholdForMinimize
) {
123 if (wm::IsWindowMaximized(window
) || wm::IsWindowFullscreen(window
)) {
124 const gfx::Rect
* restore
= GetRestoreBoundsInScreen(window
);
126 phantom_state_
= PHANTOM_WINDOW_MINIMIZED
;
129 return window
->bounds();
132 Launcher
* launcher
= Launcher::ForWindow(window
);
133 gfx::Rect rect
= launcher
->GetScreenBoundsOfItemIconForWindow(target_
);
135 rect
= launcher
->shelf_widget()->GetWindowBoundsInScreen();
138 phantom_state_
= PHANTOM_WINDOW_MINIMIZED
;
142 phantom_state_
= PHANTOM_WINDOW_NORMAL
;
143 return window
->bounds();
146 } // namespace internal