Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(594)

Side by Side Diff: ash/wm/caption_buttons/alternate_frame_size_button.cc

Issue 168943006: Keep the size button pressed when the user hovers the snap left or snap right button (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/wm/caption_buttons/alternate_frame_size_button.h" 5 #include "ash/wm/caption_buttons/alternate_frame_size_button.h"
6 6
7 #include "ash/metrics/user_metrics_recorder.h" 7 #include "ash/metrics/user_metrics_recorder.h"
8 #include "ash/screen_util.h" 8 #include "ash/screen_util.h"
9 #include "ash/shell.h" 9 #include "ash/shell.h"
10 #include "ash/touch/touch_uma.h" 10 #include "ash/touch/touch_uma.h"
11 #include "ash/wm/window_state.h" 11 #include "ash/wm/window_state.h"
12 #include "ash/wm/workspace/phantom_window_controller.h" 12 #include "ash/wm/workspace/phantom_window_controller.h"
13 #include "ash/wm/workspace/snap_sizer.h" 13 #include "ash/wm/workspace/snap_sizer.h"
14 #include "ui/gfx/vector2d.h" 14 #include "ui/gfx/vector2d.h"
15 #include "ui/views/widget/widget.h" 15 #include "ui/views/widget/widget.h"
16 16
17 namespace { 17 namespace {
18 18
19 // The default delay between the user pressing the size button and the buttons 19 // The default delay between the user pressing the size button and the buttons
20 // adjacent to the size button morphing into buttons for snapping left and 20 // adjacent to the size button morphing into buttons for snapping left and
21 // right. 21 // right.
22 const int kSetButtonsToSnapModeDelayMs = 150; 22 const int kSetButtonsToSnapModeDelayMs = 150;
23 23
24 // The amount that a user can overshoot the snap left / snap right button and 24 // The amount that a user can overshoot one of the caption buttons while in
25 // keep the snap left / snap right button pressed. 25 // "snap mode" and keep the button hovered/pressed.
26 const int kPressedHitBoundsExpandX = 200; 26 const int kMaxOvershootX = 200;
27 const int kPressedHitBoundsExpandY = 50; 27 const int kMaxOvershootY = 50;
28
29 // Returns true if a mouse drag while in "snap mode" at |location_in_screen|
30 // would hover/press |button| or keep it hovered/pressed.
31 bool HitTestButton(const ash::FrameCaptionButton* button,
32 const gfx::Point& location_in_screen) {
33 gfx::Rect expanded_bounds_in_screen = button->GetBoundsInScreen();
34 if (button->state() == views::Button::STATE_HOVERED ||
35 button->state() == views::Button::STATE_PRESSED) {
36 expanded_bounds_in_screen.Inset(-kMaxOvershootX, -kMaxOvershootY);
37 }
38 return expanded_bounds_in_screen.Contains(location_in_screen);
39 }
28 40
29 } // namespace 41 } // namespace
30 42
31 namespace ash { 43 namespace ash {
32 44
33 AlternateFrameSizeButton::AlternateFrameSizeButton( 45 AlternateFrameSizeButton::AlternateFrameSizeButton(
34 views::ButtonListener* listener, 46 views::ButtonListener* listener,
35 views::Widget* frame, 47 views::Widget* frame,
36 AlternateFrameSizeButtonDelegate* delegate) 48 AlternateFrameSizeButtonDelegate* delegate)
37 : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE), 49 : FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE),
(...skipping 14 matching lines...) Expand all
52 if (IsTriggerableEvent(event) && 64 if (IsTriggerableEvent(event) &&
53 !in_snap_mode_ && 65 !in_snap_mode_ &&
54 delegate_->IsMinimizeButtonVisible()) { 66 delegate_->IsMinimizeButtonVisible()) {
55 StartSetButtonsToSnapModeTimer(event); 67 StartSetButtonsToSnapModeTimer(event);
56 } 68 }
57 FrameCaptionButton::OnMousePressed(event); 69 FrameCaptionButton::OnMousePressed(event);
58 return true; 70 return true;
59 } 71 }
60 72
61 bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) { 73 bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) {
62 UpdatePressedButton(event); 74 UpdateSnapType(event);
63 FrameCaptionButton::OnMouseDragged(event); 75 // By default a FrameCaptionButton reverts to STATE_NORMAL once the mouse
76 // leaves its bounds. Skip FrameCaptionButton's handling when
77 // |in_snap_mode_| == true because we want different behavior.
78 if (!in_snap_mode_)
79 FrameCaptionButton::OnMouseDragged(event);
64 return true; 80 return true;
65 } 81 }
66 82
67 void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) { 83 void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) {
68 if (!IsTriggerableEvent(event) || !CommitSnap(event)) 84 if (!IsTriggerableEvent(event) || !CommitSnap(event))
69 FrameCaptionButton::OnMouseReleased(event); 85 FrameCaptionButton::OnMouseReleased(event);
70 } 86 }
71 87
72 void AlternateFrameSizeButton::OnMouseCaptureLost() { 88 void AlternateFrameSizeButton::OnMouseCaptureLost() {
73 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); 89 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
74 FrameCaptionButton::OnMouseCaptureLost(); 90 FrameCaptionButton::OnMouseCaptureLost();
75 } 91 }
76 92
93 void AlternateFrameSizeButton::OnMouseMoved(const ui::MouseEvent& event) {
94 // Ignore any synthetic mouse moves during a drag.
95 if (!in_snap_mode_)
96 FrameCaptionButton::OnMouseMoved(event);
97 }
98
77 void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) { 99 void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) {
78 if (event->details().touch_points() > 1) { 100 if (event->details().touch_points() > 1) {
79 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); 101 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
80 return; 102 return;
81 } 103 }
82 104
83 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { 105 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
84 StartSetButtonsToSnapModeTimer(*event); 106 StartSetButtonsToSnapModeTimer(*event);
85 // Go through FrameCaptionButton's handling so that the button gets pressed. 107 // Go through FrameCaptionButton's handling so that the button gets pressed.
86 FrameCaptionButton::OnGestureEvent(event); 108 FrameCaptionButton::OnGestureEvent(event);
87 return; 109 return;
88 } 110 }
89 111
90 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || 112 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
91 event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { 113 event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
92 UpdatePressedButton(*event); 114 UpdateSnapType(*event);
93 event->SetHandled(); 115 event->SetHandled();
94 return; 116 return;
95 } 117 }
96 118
97 if (event->type() == ui::ET_GESTURE_TAP || 119 if (event->type() == ui::ET_GESTURE_TAP ||
98 event->type() == ui::ET_GESTURE_SCROLL_END || 120 event->type() == ui::ET_GESTURE_SCROLL_END ||
99 event->type() == ui::ET_SCROLL_FLING_START || 121 event->type() == ui::ET_SCROLL_FLING_START ||
100 event->type() == ui::ET_GESTURE_END) { 122 event->type() == ui::ET_GESTURE_END) {
101 if (CommitSnap(*event)) { 123 if (CommitSnap(*event)) {
102 if (event->type() == ui::ET_GESTURE_TAP) { 124 if (event->type() == ui::ET_GESTURE_TAP) {
(...skipping 24 matching lines...) Expand all
127 149
128 void AlternateFrameSizeButton::SetButtonsToSnapMode() { 150 void AlternateFrameSizeButton::SetButtonsToSnapMode() {
129 if (in_snap_mode_) 151 if (in_snap_mode_)
130 return; 152 return;
131 in_snap_mode_ = true; 153 in_snap_mode_ = true;
132 delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_LEFT_SNAPPED, 154 delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_LEFT_SNAPPED,
133 CAPTION_BUTTON_ICON_RIGHT_SNAPPED, 155 CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
134 AlternateFrameSizeButtonDelegate::ANIMATE_YES); 156 AlternateFrameSizeButtonDelegate::ANIMATE_YES);
135 } 157 }
136 158
137 void AlternateFrameSizeButton::UpdatePressedButton( 159 void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) {
138 const ui::LocatedEvent& event) {
139 if (!in_snap_mode_) { 160 if (!in_snap_mode_) {
140 // Set the buttons adjacent to the size button to snap left and right early 161 // Set the buttons adjacent to the size button to snap left and right early
141 // if the user drags past the drag threshold. 162 // if the user drags past the drag threshold.
142 // |set_buttons_to_snap_mode_timer_| is checked to avoid entering the snap 163 // |set_buttons_to_snap_mode_timer_| is checked to avoid entering the snap
143 // mode as a result of an unsupported drag type (e.g. only the right mouse 164 // mode as a result of an unsupported drag type (e.g. only the right mouse
144 // button is pressed). 165 // button is pressed).
145 gfx::Vector2d delta( 166 gfx::Vector2d delta(
146 event.location() - set_buttons_to_snap_mode_timer_event_location_); 167 event.location() - set_buttons_to_snap_mode_timer_event_location_);
147 if (!set_buttons_to_snap_mode_timer_.IsRunning() || 168 if (!set_buttons_to_snap_mode_timer_.IsRunning() ||
148 !views::View::ExceededDragThreshold(delta)) { 169 !views::View::ExceededDragThreshold(delta)) {
149 return; 170 return;
150 } 171 }
151 SetButtonsToSnapMode(); 172 SetButtonsToSnapMode();
152 } 173 }
153 174
154 gfx::Point event_location_in_screen(event.location()); 175 gfx::Point event_location_in_screen(event.location());
155 views::View::ConvertPointToScreen(this, &event_location_in_screen); 176 views::View::ConvertPointToScreen(this, &event_location_in_screen);
177 const FrameCaptionButton* to_hover =
178 GetButtonToHover(event_location_in_screen);
179 bool press_size_button =
180 to_hover || HitTestButton(this, event_location_in_screen);
181 delegate_->SetHoveredAndPressedButtons(
182 to_hover, press_size_button ? this : NULL);
156 183
157 gfx::Insets pressed_button_hittest_insets(-kPressedHitBoundsExpandY,
158 -kPressedHitBoundsExpandX,
159 -kPressedHitBoundsExpandY,
160 -kPressedHitBoundsExpandX);
161 const FrameCaptionButton* pressed_button = delegate_->PressButtonAt(
162 event_location_in_screen, pressed_button_hittest_insets);
163 snap_type_ = SNAP_NONE; 184 snap_type_ = SNAP_NONE;
164 if (pressed_button) { 185 if (to_hover) {
165 switch (pressed_button->icon()) { 186 switch (to_hover->icon()) {
166 case CAPTION_BUTTON_ICON_LEFT_SNAPPED: 187 case CAPTION_BUTTON_ICON_LEFT_SNAPPED:
167 snap_type_ = SNAP_LEFT; 188 snap_type_ = SNAP_LEFT;
168 break; 189 break;
169 case CAPTION_BUTTON_ICON_RIGHT_SNAPPED: 190 case CAPTION_BUTTON_ICON_RIGHT_SNAPPED:
170 snap_type_ = SNAP_RIGHT; 191 snap_type_ = SNAP_RIGHT;
171 break; 192 break;
172 case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE: 193 case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE:
173 // snap_type_ = SNAP_NONE
174 break;
175 case CAPTION_BUTTON_ICON_MINIMIZE: 194 case CAPTION_BUTTON_ICON_MINIMIZE:
176 case CAPTION_BUTTON_ICON_CLOSE: 195 case CAPTION_BUTTON_ICON_CLOSE:
177 NOTREACHED(); 196 NOTREACHED();
178 break; 197 break;
179 } 198 }
180 } 199 }
181 200
182 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { 201 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) {
183 if (!phantom_window_controller_.get()) { 202 if (!phantom_window_controller_.get()) {
184 phantom_window_controller_.reset( 203 phantom_window_controller_.reset(
185 new internal::PhantomWindowController(frame_->GetNativeWindow())); 204 new internal::PhantomWindowController(frame_->GetNativeWindow()));
186 } 205 }
187 206
188 using internal::SnapSizer; 207 using internal::SnapSizer;
189 SnapSizer snap_sizer(wm::GetWindowState(frame_->GetNativeWindow()), 208 SnapSizer snap_sizer(wm::GetWindowState(frame_->GetNativeWindow()),
190 gfx::Point(), 209 gfx::Point(),
191 snap_type_ == SNAP_LEFT ? 210 snap_type_ == SNAP_LEFT ?
192 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE, 211 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE,
193 SnapSizer::OTHER_INPUT); 212 SnapSizer::OTHER_INPUT);
194 phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen( 213 phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen(
195 frame_->GetNativeView()->parent(), 214 frame_->GetNativeView()->parent(),
196 snap_sizer.target_bounds())); 215 snap_sizer.target_bounds()));
197 } else { 216 } else {
198 phantom_window_controller_.reset(); 217 phantom_window_controller_.reset();
199 } 218 }
200 } 219 }
201 220
221 const FrameCaptionButton* AlternateFrameSizeButton::GetButtonToHover(
222 const gfx::Point& event_location_in_screen) const {
223 const FrameCaptionButton* closest_button = delegate_->GetButtonClosestTo(
224 event_location_in_screen);
225 if ((closest_button->icon() == CAPTION_BUTTON_ICON_LEFT_SNAPPED ||
226 closest_button->icon() == CAPTION_BUTTON_ICON_RIGHT_SNAPPED) &&
227 HitTestButton(closest_button, event_location_in_screen)) {
228 return closest_button;
229 }
230 return NULL;
231 }
232
202 bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) { 233 bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) {
203 // The position of |event| may be different than the position of the previous 234 // The position of |event| may be different than the position of the previous
204 // event. 235 // event.
205 UpdatePressedButton(event); 236 UpdateSnapType(event);
206 237
207 if (in_snap_mode_ && 238 if (in_snap_mode_ &&
208 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { 239 (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) {
209 using internal::SnapSizer; 240 using internal::SnapSizer;
210 SnapSizer::SnapWindow(ash::wm::GetWindowState(frame_->GetNativeWindow()), 241 SnapSizer::SnapWindow(ash::wm::GetWindowState(frame_->GetNativeWindow()),
211 snap_type_ == SNAP_LEFT ? 242 snap_type_ == SNAP_LEFT ?
212 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE); 243 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE);
213 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( 244 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction(
214 snap_type_ == SNAP_LEFT ? 245 snap_type_ == SNAP_LEFT ?
215 ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT : 246 ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT :
216 ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT); 247 ash::UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT);
217 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO); 248 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO);
218 return true; 249 return true;
219 } 250 }
220 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES); 251 SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
221 return false; 252 return false;
222 } 253 }
223 254
224 void AlternateFrameSizeButton::SetButtonsToNormalMode( 255 void AlternateFrameSizeButton::SetButtonsToNormalMode(
225 AlternateFrameSizeButtonDelegate::Animate animate) { 256 AlternateFrameSizeButtonDelegate::Animate animate) {
226 in_snap_mode_ = false; 257 in_snap_mode_ = false;
227 snap_type_ = SNAP_NONE; 258 snap_type_ = SNAP_NONE;
228 set_buttons_to_snap_mode_timer_.Stop(); 259 set_buttons_to_snap_mode_timer_.Stop();
229 delegate_->SetButtonsToNormal(animate); 260 delegate_->SetButtonsToNormal(animate);
230 phantom_window_controller_.reset(); 261 phantom_window_controller_.reset();
231 } 262 }
232 263
233 } // namespace ash 264 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698