OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/workspace/frame_maximize_button.h" | 5 #include "ash/wm/workspace/frame_maximize_button.h" |
6 | 6 |
7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/wm/property_util.h" | 8 #include "ash/wm/property_util.h" |
9 #include "ash/launcher/launcher.h" | 9 #include "ash/launcher/launcher.h" |
10 #include "ash/wm/workspace/phantom_window_controller.h" | 10 #include "ash/wm/workspace/phantom_window_controller.h" |
11 #include "ash/wm/workspace/workspace_window_resizer.h" | 11 #include "ash/wm/workspace/snap_sizer.h" |
12 #include "grit/ui_resources.h" | 12 #include "grit/ui_resources.h" |
13 #include "ui/aura/event.h" | 13 #include "ui/aura/event.h" |
14 #include "ui/aura/event_filter.h" | 14 #include "ui/aura/event_filter.h" |
15 #include "ui/base/resource/resource_bundle.h" | 15 #include "ui/base/resource/resource_bundle.h" |
16 #include "ui/gfx/image/image.h" | 16 #include "ui/gfx/image/image.h" |
17 #include "ui/gfx/screen.h" | 17 #include "ui/gfx/screen.h" |
18 #include "ui/views/widget/widget.h" | 18 #include "ui/views/widget/widget.h" |
19 | 19 |
| 20 using ash::internal::SnapSizer; |
| 21 |
20 namespace ash { | 22 namespace ash { |
21 | 23 |
22 // EscapeEventFilter is installed on the RootWindow to track when the escape key | 24 // EscapeEventFilter is installed on the RootWindow to track when the escape key |
23 // is pressed. We use an EventFilter for this as the FrameMaximizeButton | 25 // is pressed. We use an EventFilter for this as the FrameMaximizeButton |
24 // normally does not get focus. | 26 // normally does not get focus. |
25 class FrameMaximizeButton::EscapeEventFilter : public aura::EventFilter { | 27 class FrameMaximizeButton::EscapeEventFilter : public aura::EventFilter { |
26 public: | 28 public: |
27 explicit EscapeEventFilter(FrameMaximizeButton* button); | 29 explicit EscapeEventFilter(FrameMaximizeButton* button); |
28 virtual ~EscapeEventFilter(); | 30 virtual ~EscapeEventFilter(); |
29 | 31 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // TODO(sky): nuke this. It's temporary while we don't have good images. | 95 // TODO(sky): nuke this. It's temporary while we don't have good images. |
94 SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); | 96 SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); |
95 } | 97 } |
96 | 98 |
97 FrameMaximizeButton::~FrameMaximizeButton() { | 99 FrameMaximizeButton::~FrameMaximizeButton() { |
98 } | 100 } |
99 | 101 |
100 bool FrameMaximizeButton::OnMousePressed(const views::MouseEvent& event) { | 102 bool FrameMaximizeButton::OnMousePressed(const views::MouseEvent& event) { |
101 is_snap_enabled_ = event.IsLeftMouseButton(); | 103 is_snap_enabled_ = event.IsLeftMouseButton(); |
102 if (is_snap_enabled_) { | 104 if (is_snap_enabled_) { |
| 105 snap_sizer_.reset(NULL); |
103 InstallEventFilter(); | 106 InstallEventFilter(); |
104 snap_type_ = SNAP_NONE; | 107 snap_type_ = SNAP_NONE; |
105 press_location_ = event.location(); | 108 press_location_ = event.location(); |
106 exceeded_drag_threshold_ = false; | 109 exceeded_drag_threshold_ = false; |
107 } | 110 } |
108 ImageButton::OnMousePressed(event); | 111 ImageButton::OnMousePressed(event); |
109 return true; | 112 return true; |
110 } | 113 } |
111 | 114 |
112 void FrameMaximizeButton::OnMouseEntered(const views::MouseEvent& event) { | 115 void FrameMaximizeButton::OnMouseEntered(const views::MouseEvent& event) { |
113 ImageButton::OnMouseEntered(event); | 116 ImageButton::OnMouseEntered(event); |
114 } | 117 } |
115 | 118 |
116 void FrameMaximizeButton::OnMouseExited(const views::MouseEvent& event) { | 119 void FrameMaximizeButton::OnMouseExited(const views::MouseEvent& event) { |
117 ImageButton::OnMouseExited(event); | 120 ImageButton::OnMouseExited(event); |
118 } | 121 } |
119 | 122 |
120 bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { | 123 bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { |
121 if (is_snap_enabled_) { | 124 if (is_snap_enabled_) { |
122 int delta_x = event.location().x() - press_location_.x(); | 125 int delta_x = event.location().x() - press_location_.x(); |
123 int delta_y = event.location().y() - press_location_.y(); | 126 int delta_y = event.location().y() - press_location_.y(); |
124 if (!exceeded_drag_threshold_) { | 127 if (!exceeded_drag_threshold_) { |
125 exceeded_drag_threshold_ = | 128 exceeded_drag_threshold_ = |
126 views::View::ExceededDragThreshold(delta_x, delta_y); | 129 views::View::ExceededDragThreshold(delta_x, delta_y); |
127 } | 130 } |
128 if (exceeded_drag_threshold_) | 131 if (exceeded_drag_threshold_) |
129 UpdateSnap(delta_x, delta_y); | 132 UpdateSnap(event.location()); |
130 } | 133 } |
131 return ImageButton::OnMouseDragged(event); | 134 return ImageButton::OnMouseDragged(event); |
132 } | 135 } |
133 | 136 |
134 void FrameMaximizeButton::OnMouseReleased(const views::MouseEvent& event) { | 137 void FrameMaximizeButton::OnMouseReleased(const views::MouseEvent& event) { |
135 UninstallEventFilter(); | 138 UninstallEventFilter(); |
136 bool should_snap = is_snap_enabled_; | 139 bool should_snap = is_snap_enabled_; |
137 is_snap_enabled_ = false; | 140 is_snap_enabled_ = false; |
138 if (should_snap && snap_type_ != SNAP_NONE) { | 141 if (should_snap && snap_type_ != SNAP_NONE) { |
139 SetState(BS_NORMAL); | 142 SetState(BS_NORMAL); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 194 } |
192 return *ResourceBundle::GetSharedInstance().GetImageNamed(id).ToSkBitmap(); | 195 return *ResourceBundle::GetSharedInstance().GetImageNamed(id).ToSkBitmap(); |
193 } | 196 } |
194 return ImageButton::GetImageToPaint(); | 197 return ImageButton::GetImageToPaint(); |
195 } | 198 } |
196 | 199 |
197 void FrameMaximizeButton::Cancel() { | 200 void FrameMaximizeButton::Cancel() { |
198 UninstallEventFilter(); | 201 UninstallEventFilter(); |
199 is_snap_enabled_ = false; | 202 is_snap_enabled_ = false; |
200 phantom_window_.reset(); | 203 phantom_window_.reset(); |
| 204 snap_sizer_.reset(); |
201 SchedulePaint(); | 205 SchedulePaint(); |
202 } | 206 } |
203 | 207 |
204 void FrameMaximizeButton::InstallEventFilter() { | 208 void FrameMaximizeButton::InstallEventFilter() { |
205 if (escape_event_filter_.get()) | 209 if (escape_event_filter_.get()) |
206 return; | 210 return; |
207 | 211 |
208 escape_event_filter_.reset(new EscapeEventFilter(this)); | 212 escape_event_filter_.reset(new EscapeEventFilter(this)); |
209 } | 213 } |
210 | 214 |
211 void FrameMaximizeButton::UninstallEventFilter() { | 215 void FrameMaximizeButton::UninstallEventFilter() { |
212 escape_event_filter_.reset(NULL); | 216 escape_event_filter_.reset(NULL); |
213 } | 217 } |
214 | 218 |
215 void FrameMaximizeButton::UpdateSnap(int delta_x, int delta_y) { | 219 void FrameMaximizeButton::UpdateSnap(const gfx::Point& location) { |
216 SnapType type = SnapTypeForDelta(delta_x, delta_y); | 220 SnapType type = SnapTypeForLocation(location); |
217 if (type == snap_type_) | 221 if (type == snap_type_) { |
218 return; | 222 if (snap_sizer_.get()) { |
219 | 223 snap_sizer_->Update(LocationForSnapSizer(location)); |
220 SchedulePaint(); | 224 phantom_window_->Show(snap_sizer_->target_bounds()); |
221 | 225 } |
222 if (type == SNAP_NONE) { | |
223 phantom_window_.reset(); | |
224 snap_type_ = SNAP_NONE; | |
225 return; | 226 return; |
226 } | 227 } |
227 | 228 |
228 snap_type_ = type; | 229 snap_type_ = type; |
| 230 snap_sizer_.reset(); |
| 231 SchedulePaint(); |
| 232 |
| 233 if (snap_type_ == SNAP_NONE) { |
| 234 phantom_window_.reset(); |
| 235 return; |
| 236 } |
| 237 |
| 238 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { |
| 239 SnapSizer::Edge snap_edge = snap_type_ == SNAP_LEFT ? |
| 240 SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; |
| 241 int grid_size = Shell::GetInstance()->GetGridSize(); |
| 242 snap_sizer_.reset(new SnapSizer(GetWidget()->GetNativeWindow(), |
| 243 LocationForSnapSizer(location), |
| 244 snap_edge, grid_size)); |
| 245 } |
229 if (!phantom_window_.get()) { | 246 if (!phantom_window_.get()) { |
230 phantom_window_.reset(new internal::PhantomWindowController( | 247 phantom_window_.reset(new internal::PhantomWindowController( |
231 GetWidget()->GetNativeWindow(), | 248 GetWidget()->GetNativeWindow(), |
232 internal::PhantomWindowController::TYPE_EDGE, 0)); | 249 internal::PhantomWindowController::TYPE_EDGE, 0)); |
233 } | 250 } |
234 phantom_window_->Show(BoundsForType(snap_type_)); | 251 phantom_window_->Show(BoundsForType(snap_type_)); |
235 } | 252 } |
236 | 253 |
237 FrameMaximizeButton::SnapType FrameMaximizeButton::SnapTypeForDelta( | 254 FrameMaximizeButton::SnapType FrameMaximizeButton::SnapTypeForLocation( |
238 int delta_x, | 255 const gfx::Point& location) const { |
239 int delta_y) const { | 256 int delta_x = location.x() - press_location_.x(); |
| 257 int delta_y = location.y() - press_location_.y(); |
240 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) | 258 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) |
241 return GetWidget()->IsMaximized() ? SNAP_NONE : SNAP_MAXIMIZE; | 259 return GetWidget()->IsMaximized() ? SNAP_NONE : SNAP_MAXIMIZE; |
242 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) | 260 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) |
243 return SNAP_LEFT; | 261 return SNAP_LEFT; |
244 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) | 262 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) |
245 return SNAP_RIGHT; | 263 return SNAP_RIGHT; |
246 else if (delta_y > 0) | 264 else if (delta_y > 0) |
247 return SNAP_MINIMIZE; | 265 return SNAP_MINIMIZE; |
248 return GetWidget()->IsMaximized() ? SNAP_NONE : SNAP_MAXIMIZE; | 266 return GetWidget()->IsMaximized() ? SNAP_NONE : SNAP_MAXIMIZE; |
249 } | 267 } |
250 | 268 |
251 gfx::Rect FrameMaximizeButton::BoundsForType(SnapType type) const { | 269 gfx::Rect FrameMaximizeButton::BoundsForType(SnapType type) const { |
252 aura::Window* window = GetWidget()->GetNativeWindow(); | 270 aura::Window* window = GetWidget()->GetNativeWindow(); |
253 int grid_size = Shell::GetInstance()->GetGridSize(); | |
254 switch (type) { | 271 switch (type) { |
255 case SNAP_LEFT: | 272 case SNAP_LEFT: |
256 return internal::WorkspaceWindowResizer::GetBoundsForWindowAlongEdge( | |
257 window, internal::WorkspaceWindowResizer::LEFT_EDGE, grid_size); | |
258 case SNAP_RIGHT: | 273 case SNAP_RIGHT: |
259 return internal::WorkspaceWindowResizer::GetBoundsForWindowAlongEdge( | 274 return snap_sizer_->target_bounds(); |
260 window, internal::WorkspaceWindowResizer::RIGHT_EDGE, grid_size); | |
261 case SNAP_MAXIMIZE: | 275 case SNAP_MAXIMIZE: |
262 return gfx::Screen::GetMonitorWorkAreaNearestWindow(window); | 276 return gfx::Screen::GetMonitorWorkAreaNearestWindow(window); |
263 case SNAP_MINIMIZE: { | 277 case SNAP_MINIMIZE: { |
264 Launcher* launcher = Shell::GetInstance()->launcher(); | 278 Launcher* launcher = Shell::GetInstance()->launcher(); |
265 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); | 279 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); |
266 if (!item_rect.IsEmpty()) { | 280 if (!item_rect.IsEmpty()) { |
267 // PhantomWindowController insets slightly, outset it so the phantom | 281 // PhantomWindowController insets slightly, outset it so the phantom |
268 // doesn't appear inset. | 282 // doesn't appear inset. |
269 item_rect.Inset(-8, -8); | 283 item_rect.Inset(-8, -8); |
270 return item_rect; | 284 return item_rect; |
271 } | 285 } |
272 return launcher->widget()->GetWindowScreenBounds(); | 286 return launcher->widget()->GetWindowScreenBounds(); |
273 } | 287 } |
274 default: | 288 default: |
275 NOTREACHED(); | 289 NOTREACHED(); |
276 } | 290 } |
277 return gfx::Rect(); | 291 return gfx::Rect(); |
278 } | 292 } |
279 | 293 |
| 294 gfx::Point FrameMaximizeButton::LocationForSnapSizer( |
| 295 const gfx::Point& location) const { |
| 296 gfx::Point result(location); |
| 297 views::View::ConvertPointToScreen(this, &result); |
| 298 return result; |
| 299 } |
| 300 |
280 void FrameMaximizeButton::Snap() { | 301 void FrameMaximizeButton::Snap() { |
281 switch (snap_type_) { | 302 switch (snap_type_) { |
282 case SNAP_LEFT: | 303 case SNAP_LEFT: |
283 case SNAP_RIGHT: | 304 case SNAP_RIGHT: |
284 if (GetWidget()->IsMaximized()) { | 305 if (GetWidget()->IsMaximized()) { |
285 ash::SetRestoreBounds(GetWidget()->GetNativeWindow(), | 306 ash::SetRestoreBounds(GetWidget()->GetNativeWindow(), |
286 BoundsForType(snap_type_)); | 307 BoundsForType(snap_type_)); |
287 GetWidget()->Restore(); | 308 GetWidget()->Restore(); |
288 } else { | 309 } else { |
289 GetWidget()->SetBounds(BoundsForType(snap_type_)); | 310 GetWidget()->SetBounds(BoundsForType(snap_type_)); |
290 } | 311 } |
291 break; | 312 break; |
292 case SNAP_MAXIMIZE: | 313 case SNAP_MAXIMIZE: |
293 GetWidget()->Maximize(); | 314 GetWidget()->Maximize(); |
294 break; | 315 break; |
295 case SNAP_MINIMIZE: | 316 case SNAP_MINIMIZE: |
296 GetWidget()->Minimize(); | 317 GetWidget()->Minimize(); |
297 break; | 318 break; |
298 default: | 319 default: |
299 NOTREACHED(); | 320 NOTREACHED(); |
300 } | 321 } |
301 } | 322 } |
302 | 323 |
303 } // namespace ash | 324 } // namespace ash |
OLD | NEW |