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/launcher/launcher.h" | 7 #include "ash/launcher/launcher.h" |
8 #include "ash/screen_ash.h" | 8 #include "ash/screen_ash.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ash/wm/property_util.h" | 10 #include "ash/wm/property_util.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 frame_(frame), | 106 frame_(frame), |
107 is_snap_enabled_(false), | 107 is_snap_enabled_(false), |
108 exceeded_drag_threshold_(false), | 108 exceeded_drag_threshold_(false), |
109 window_(NULL), | 109 window_(NULL), |
110 snap_type_(SNAP_NONE) { | 110 snap_type_(SNAP_NONE) { |
111 // TODO(sky): nuke this. It's temporary while we don't have good images. | 111 // TODO(sky): nuke this. It's temporary while we don't have good images. |
112 SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); | 112 SetImageAlignment(ALIGN_LEFT, ALIGN_BOTTOM); |
113 } | 113 } |
114 | 114 |
115 FrameMaximizeButton::~FrameMaximizeButton() { | 115 FrameMaximizeButton::~FrameMaximizeButton() { |
| 116 // Before the window gets destroyed, the maximizer dialog needs to be shut |
| 117 // down since it would otherwise call into a deleted object. |
| 118 maximizer_.reset(); |
116 if (window_) | 119 if (window_) |
117 OnWindowDestroying(window_); | 120 OnWindowDestroying(window_); |
118 } | 121 } |
119 | 122 |
120 void FrameMaximizeButton::SnapButtonHovered(SnapType type) { | 123 void FrameMaximizeButton::SnapButtonHovered(SnapType type) { |
121 // Make sure to only show hover operations when no button is pressed and | 124 // Make sure to only show hover operations when no button is pressed and |
122 // a similar snap operation in progress does not get re-applied. | 125 // a similar snap operation in progress does not get re-applied. |
123 if (is_snap_enabled_ || (type == snap_type_ && snap_sizer_.get())) | 126 if (is_snap_enabled_ || (type == snap_type_ && snap_sizer_.get())) |
124 return; | 127 return; |
125 // Prime the mouse location with the center of the (local) button. | 128 // Prime the mouse location with the center of the (local) button. |
(...skipping 18 matching lines...) Expand all Loading... |
144 return; | 147 return; |
145 default: | 148 default: |
146 // We should not come here. | 149 // We should not come here. |
147 NOTREACHED(); | 150 NOTREACHED(); |
148 } | 151 } |
149 UpdateSnap(location); | 152 UpdateSnap(location); |
150 } | 153 } |
151 | 154 |
152 void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) { | 155 void FrameMaximizeButton::ExecuteSnapAndCloseMenu(SnapType snap_type) { |
153 DCHECK_NE(snap_type_, SNAP_NONE); | 156 DCHECK_NE(snap_type_, SNAP_NONE); |
| 157 Cancel(true); |
| 158 // Tell our menu to close. |
| 159 maximizer_.reset(); |
154 snap_type_ = snap_type; | 160 snap_type_ = snap_type; |
155 Snap(); | 161 // Since Snap might destroy |this|, but the snap_sizer needs to be destroyed, |
156 // Remove any pending snap previews. | 162 // The ownership of the snap_sizer is taken now. |
157 SnapButtonHovered(SNAP_NONE); | 163 scoped_ptr<SnapSizer> snap_sizer(snap_sizer_.release()); |
158 // At this point the operation has been performed and the menu should be | 164 Snap(*snap_sizer.get()); |
159 // closed - if not, it'll get now closed. | |
160 maximizer_.reset(); | |
161 } | 165 } |
162 | 166 |
163 void FrameMaximizeButton::DestroyMaximizeMenu() { | 167 void FrameMaximizeButton::DestroyMaximizeMenu() { |
164 maximizer_.reset(); | 168 maximizer_.reset(); |
165 } | 169 } |
166 | 170 |
167 void FrameMaximizeButton::OnWindowBoundsChanged( | 171 void FrameMaximizeButton::OnWindowBoundsChanged( |
168 aura::Window* window, | 172 aura::Window* window, |
169 const gfx::Rect& old_bounds, | 173 const gfx::Rect& old_bounds, |
170 const gfx::Rect& new_bounds) { | 174 const gfx::Rect& new_bounds) { |
(...skipping 28 matching lines...) Expand all Loading... |
199 maximizer_.reset(new MaximizeBubbleController( | 203 maximizer_.reset(new MaximizeBubbleController( |
200 this, | 204 this, |
201 frame_->GetWidget()->IsMaximized())); | 205 frame_->GetWidget()->IsMaximized())); |
202 } | 206 } |
203 } | 207 } |
204 | 208 |
205 void FrameMaximizeButton::OnMouseExited(const views::MouseEvent& event) { | 209 void FrameMaximizeButton::OnMouseExited(const views::MouseEvent& event) { |
206 ImageButton::OnMouseExited(event); | 210 ImageButton::OnMouseExited(event); |
207 // Remove the bubble menu when the button is not pressed and the mouse is not | 211 // Remove the bubble menu when the button is not pressed and the mouse is not |
208 // within the bubble. | 212 // within the bubble. |
209 if (!is_snap_enabled_ && maximizer_.get() && maximizer_->GetBubbleWindow()) { | 213 if (!is_snap_enabled_ && maximizer_.get()) { |
210 gfx::Point screen_location = gfx::Screen::GetCursorScreenPoint(); | 214 if (maximizer_->GetBubbleWindow()) { |
211 if (!maximizer_->GetBubbleWindow()->GetBoundsInScreen().Contains( | 215 gfx::Point screen_location = gfx::Screen::GetCursorScreenPoint(); |
212 screen_location)) { | 216 if (!maximizer_->GetBubbleWindow()->GetBoundsInScreen().Contains( |
| 217 screen_location)) { |
| 218 maximizer_.reset(); |
| 219 // Make sure that all remaining snap hover states get removed. |
| 220 SnapButtonHovered(SNAP_NONE); |
| 221 } |
| 222 } else { |
| 223 // The maximize dialog does not show up immediately after creating the |
| 224 // |mazimizer_|. Destroy the dialog therefore before it shows up. |
213 maximizer_.reset(); | 225 maximizer_.reset(); |
214 // Make sure that all remaining snap hover states get removed. | |
215 SnapButtonHovered(SNAP_NONE); | |
216 } | 226 } |
217 } | 227 } |
218 } | 228 } |
219 | 229 |
220 bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { | 230 bool FrameMaximizeButton::OnMouseDragged(const views::MouseEvent& event) { |
221 if (is_snap_enabled_) | 231 if (is_snap_enabled_) |
222 ProcessUpdateEvent(event); | 232 ProcessUpdateEvent(event); |
223 return ImageButton::OnMouseDragged(event); | 233 return ImageButton::OnMouseDragged(event); |
224 } | 234 } |
225 | 235 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 maximizer_.reset(); | 324 maximizer_.reset(); |
315 | 325 |
316 if (!should_snap || snap_type_ == SNAP_NONE) | 326 if (!should_snap || snap_type_ == SNAP_NONE) |
317 return false; | 327 return false; |
318 | 328 |
319 SetState(BS_NORMAL); | 329 SetState(BS_NORMAL); |
320 // SetState will not call SchedulePaint() if state was already set to | 330 // SetState will not call SchedulePaint() if state was already set to |
321 // BS_NORMAL during a drag. | 331 // BS_NORMAL during a drag. |
322 SchedulePaint(); | 332 SchedulePaint(); |
323 phantom_window_.reset(); | 333 phantom_window_.reset(); |
324 Snap(); | 334 // Since Snap might destroy |this|, but the snap_sizer needs to be destroyed, |
| 335 // The ownership of the snap_sizer is taken now. |
| 336 scoped_ptr<SnapSizer> snap_sizer(snap_sizer_.release()); |
| 337 Snap(*snap_sizer.get()); |
325 return true; | 338 return true; |
326 } | 339 } |
327 | 340 |
328 void FrameMaximizeButton::Cancel(bool keep_menu_open) { | 341 void FrameMaximizeButton::Cancel(bool keep_menu_open) { |
329 if (!keep_menu_open) { | 342 if (!keep_menu_open) { |
330 maximizer_.reset(); | 343 maximizer_.reset(); |
331 UninstallEventFilter(); | 344 UninstallEventFilter(); |
332 is_snap_enabled_ = false; | 345 is_snap_enabled_ = false; |
| 346 snap_sizer_.reset(); |
333 } | 347 } |
334 phantom_window_.reset(); | 348 phantom_window_.reset(); |
335 snap_sizer_.reset(); | |
336 snap_type_ = SNAP_NONE; | 349 snap_type_ = SNAP_NONE; |
337 update_timer_.Stop(); | 350 update_timer_.Stop(); |
338 SchedulePaint(); | 351 SchedulePaint(); |
339 } | 352 } |
340 | 353 |
341 void FrameMaximizeButton::InstallEventFilter() { | 354 void FrameMaximizeButton::InstallEventFilter() { |
342 if (escape_event_filter_.get()) | 355 if (escape_event_filter_.get()) |
343 return; | 356 return; |
344 | 357 |
345 escape_event_filter_.reset(new EscapeEventFilter(this)); | 358 escape_event_filter_.reset(new EscapeEventFilter(this)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 snap_edge, grid_size)); | 400 snap_edge, grid_size)); |
388 } | 401 } |
389 if (!phantom_window_.get()) { | 402 if (!phantom_window_.get()) { |
390 phantom_window_.reset(new internal::PhantomWindowController( | 403 phantom_window_.reset(new internal::PhantomWindowController( |
391 frame_->GetWidget()->GetNativeWindow())); | 404 frame_->GetWidget()->GetNativeWindow())); |
392 } | 405 } |
393 if (maximizer_.get()) { | 406 if (maximizer_.get()) { |
394 phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); | 407 phantom_window_->set_phantom_below_window(maximizer_->GetBubbleWindow()); |
395 maximizer_->SetSnapType(snap_type_); | 408 maximizer_->SetSnapType(snap_type_); |
396 } | 409 } |
397 phantom_window_->Show(ScreenBoundsForType(snap_type_)); | 410 phantom_window_->Show(ScreenBoundsForType(snap_type_, *snap_sizer_.get())); |
398 } | 411 } |
399 | 412 |
400 SnapType FrameMaximizeButton::SnapTypeForLocation( | 413 SnapType FrameMaximizeButton::SnapTypeForLocation( |
401 const gfx::Point& location) const { | 414 const gfx::Point& location) const { |
402 int delta_x = location.x() - press_location_.x(); | 415 int delta_x = location.x() - press_location_.x(); |
403 int delta_y = location.y() - press_location_.y(); | 416 int delta_y = location.y() - press_location_.y(); |
404 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) | 417 if (!views::View::ExceededDragThreshold(delta_x, delta_y)) |
405 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; | 418 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; |
406 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) | 419 else if (delta_x < 0 && delta_y > delta_x && delta_y < -delta_x) |
407 return SNAP_LEFT; | 420 return SNAP_LEFT; |
408 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) | 421 else if (delta_x > 0 && delta_y > -delta_x && delta_y < delta_x) |
409 return SNAP_RIGHT; | 422 return SNAP_RIGHT; |
410 else if (delta_y > 0) | 423 else if (delta_y > 0) |
411 return SNAP_MINIMIZE; | 424 return SNAP_MINIMIZE; |
412 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; | 425 return !frame_->GetWidget()->IsMaximized() ? SNAP_MAXIMIZE : SNAP_RESTORE; |
413 } | 426 } |
414 | 427 |
415 gfx::Rect FrameMaximizeButton::ScreenBoundsForType(SnapType type) const { | 428 gfx::Rect FrameMaximizeButton::ScreenBoundsForType( |
| 429 SnapType type, |
| 430 const SnapSizer& snap_sizer) const { |
416 aura::Window* window = frame_->GetWidget()->GetNativeWindow(); | 431 aura::Window* window = frame_->GetWidget()->GetNativeWindow(); |
417 switch (type) { | 432 switch (type) { |
418 case SNAP_LEFT: | 433 case SNAP_LEFT: |
419 case SNAP_RIGHT: | 434 case SNAP_RIGHT: |
420 return ScreenAsh::ConvertRectToScreen( | 435 return ScreenAsh::ConvertRectToScreen( |
421 frame_->GetWidget()->GetNativeView()->parent(), | 436 frame_->GetWidget()->GetNativeView()->parent(), |
422 snap_sizer_->target_bounds()); | 437 snap_sizer.target_bounds()); |
423 case SNAP_MAXIMIZE: | 438 case SNAP_MAXIMIZE: |
424 return ScreenAsh::ConvertRectToScreen( | 439 return ScreenAsh::ConvertRectToScreen( |
425 window->parent(), | 440 window->parent(), |
426 ScreenAsh::GetMaximizedWindowBoundsInParent(window)); | 441 ScreenAsh::GetMaximizedWindowBoundsInParent(window)); |
427 case SNAP_MINIMIZE: { | 442 case SNAP_MINIMIZE: { |
428 Launcher* launcher = Shell::GetInstance()->launcher(); | 443 Launcher* launcher = Shell::GetInstance()->launcher(); |
429 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); | 444 gfx::Rect item_rect(launcher->GetScreenBoundsOfItemIconForWindow(window)); |
430 if (!item_rect.IsEmpty()) { | 445 if (!item_rect.IsEmpty()) { |
431 // PhantomWindowController insets slightly, outset it so the phantom | 446 // PhantomWindowController insets slightly, outset it so the phantom |
432 // doesn't appear inset. | 447 // doesn't appear inset. |
(...skipping 13 matching lines...) Expand all Loading... |
446 return gfx::Rect(); | 461 return gfx::Rect(); |
447 } | 462 } |
448 | 463 |
449 gfx::Point FrameMaximizeButton::LocationForSnapSizer( | 464 gfx::Point FrameMaximizeButton::LocationForSnapSizer( |
450 const gfx::Point& location) const { | 465 const gfx::Point& location) const { |
451 gfx::Point result(location); | 466 gfx::Point result(location); |
452 views::View::ConvertPointToScreen(this, &result); | 467 views::View::ConvertPointToScreen(this, &result); |
453 return result; | 468 return result; |
454 } | 469 } |
455 | 470 |
456 void FrameMaximizeButton::Snap() { | 471 void FrameMaximizeButton::Snap(const SnapSizer& snap_sizer) { |
457 switch (snap_type_) { | 472 switch (snap_type_) { |
458 case SNAP_LEFT: | 473 case SNAP_LEFT: |
459 case SNAP_RIGHT: | 474 case SNAP_RIGHT: |
460 if (frame_->GetWidget()->IsMaximized()) { | 475 if (frame_->GetWidget()->IsMaximized()) { |
461 ash::SetRestoreBoundsInScreen(frame_->GetWidget()->GetNativeWindow(), | 476 ash::SetRestoreBoundsInScreen(frame_->GetWidget()->GetNativeWindow(), |
462 ScreenBoundsForType(snap_type_)); | 477 ScreenBoundsForType(snap_type_, |
| 478 snap_sizer)); |
463 frame_->GetWidget()->Restore(); | 479 frame_->GetWidget()->Restore(); |
464 } else { | 480 } else { |
465 frame_->GetWidget()->SetBounds(ScreenBoundsForType(snap_type_)); | 481 frame_->GetWidget()->SetBounds(ScreenBoundsForType(snap_type_, |
| 482 snap_sizer)); |
466 } | 483 } |
467 break; | 484 break; |
468 case SNAP_MAXIMIZE: | 485 case SNAP_MAXIMIZE: |
469 frame_->GetWidget()->Maximize(); | 486 frame_->GetWidget()->Maximize(); |
470 break; | 487 break; |
471 case SNAP_MINIMIZE: | 488 case SNAP_MINIMIZE: |
472 frame_->GetWidget()->Minimize(); | 489 frame_->GetWidget()->Minimize(); |
473 break; | 490 break; |
474 case SNAP_RESTORE: | 491 case SNAP_RESTORE: |
475 frame_->GetWidget()->Restore(); | 492 frame_->GetWidget()->Restore(); |
476 break; | 493 break; |
477 case SNAP_NONE: | 494 case SNAP_NONE: |
478 NOTREACHED(); | 495 NOTREACHED(); |
479 } | 496 } |
480 } | 497 } |
481 | 498 |
482 } // namespace ash | 499 } // namespace ash |
OLD | NEW |