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/workspace_window_resizer.h" | 5 #include "ash/wm/workspace/workspace_window_resizer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "ash/metrics/user_metrics_action.h" | 12 #include "ash/metrics/user_metrics_action.h" |
13 #include "ash/public/cpp/shell_window_ids.h" | 13 #include "ash/public/cpp/shell_window_ids.h" |
14 #include "ash/root_window_controller.h" | 14 #include "ash/root_window_controller.h" |
15 #include "ash/screen_util.h" | 15 #include "ash/screen_util.h" |
16 #include "ash/shell.h" | 16 #include "ash/shell.h" |
17 #include "ash/shell_port.h" | 17 #include "ash/shell_port.h" |
18 #include "ash/wm/default_window_resizer.h" | 18 #include "ash/wm/default_window_resizer.h" |
19 #include "ash/wm/panels/panel_window_resizer.h" | 19 #include "ash/wm/panels/panel_window_resizer.h" |
20 #include "ash/wm/window_positioning_utils.h" | 20 #include "ash/wm/window_positioning_utils.h" |
21 #include "ash/wm/window_state.h" | 21 #include "ash/wm/window_state.h" |
22 #include "ash/wm/wm_event.h" | 22 #include "ash/wm/wm_event.h" |
23 #include "ash/wm/workspace/phantom_window_controller.h" | 23 #include "ash/wm/workspace/phantom_window_controller.h" |
24 #include "ash/wm/workspace/two_step_edge_cycler.h" | 24 #include "ash/wm/workspace/two_step_edge_cycler.h" |
25 #include "ash/wm_window.h" | 25 #include "ash/wm_window.h" |
26 #include "base/memory/ptr_util.h" | 26 #include "base/memory/ptr_util.h" |
27 #include "base/memory/weak_ptr.h" | 27 #include "base/memory/weak_ptr.h" |
| 28 #include "ui/aura/window.h" |
| 29 #include "ui/aura/window_delegate.h" |
28 #include "ui/base/hit_test.h" | 30 #include "ui/base/hit_test.h" |
29 #include "ui/compositor/layer.h" | 31 #include "ui/compositor/layer.h" |
30 #include "ui/display/display.h" | 32 #include "ui/display/display.h" |
31 #include "ui/display/screen.h" | 33 #include "ui/display/screen.h" |
32 #include "ui/gfx/transform.h" | 34 #include "ui/gfx/transform.h" |
| 35 #include "ui/wm/core/coordinate_conversion.h" |
33 #include "ui/wm/public/window_types.h" | 36 #include "ui/wm/public/window_types.h" |
34 | 37 |
35 namespace ash { | 38 namespace ash { |
36 | 39 |
37 std::unique_ptr<WindowResizer> CreateWindowResizer( | 40 std::unique_ptr<WindowResizer> CreateWindowResizer( |
38 WmWindow* window, | 41 aura::Window* window, |
39 const gfx::Point& point_in_parent, | 42 const gfx::Point& point_in_parent, |
40 int window_component, | 43 int window_component, |
41 aura::client::WindowMoveSource source) { | 44 aura::client::WindowMoveSource source) { |
42 DCHECK(window); | 45 DCHECK(window); |
43 wm::WindowState* window_state = window->GetWindowState(); | 46 wm::WindowState* window_state = wm::GetWindowState(window); |
44 // No need to return a resizer when the window cannot get resized or when a | 47 // No need to return a resizer when the window cannot get resized or when a |
45 // resizer already exists for this window. | 48 // resizer already exists for this window. |
46 if ((!window_state->CanResize() && window_component != HTCAPTION) || | 49 if ((!window_state->CanResize() && window_component != HTCAPTION) || |
47 window_state->drag_details()) { | 50 window_state->drag_details()) { |
48 return nullptr; | 51 return nullptr; |
49 } | 52 } |
50 | 53 |
51 if (window_component == HTCAPTION && !window_state->can_be_dragged()) | 54 if (window_component == HTCAPTION && !window_state->can_be_dragged()) |
52 return nullptr; | 55 return nullptr; |
53 | 56 |
(...skipping 11 matching lines...) Expand all Loading... |
65 if (!window_state->IsNormalOrSnapped()) | 68 if (!window_state->IsNormalOrSnapped()) |
66 return std::unique_ptr<WindowResizer>(); | 69 return std::unique_ptr<WindowResizer>(); |
67 | 70 |
68 int bounds_change = | 71 int bounds_change = |
69 WindowResizer::GetBoundsChangeForWindowComponent(window_component); | 72 WindowResizer::GetBoundsChangeForWindowComponent(window_component); |
70 if (bounds_change == WindowResizer::kBoundsChangeDirection_None) | 73 if (bounds_change == WindowResizer::kBoundsChangeDirection_None) |
71 return std::unique_ptr<WindowResizer>(); | 74 return std::unique_ptr<WindowResizer>(); |
72 | 75 |
73 window_state->CreateDragDetails(point_in_parent, window_component, source); | 76 window_state->CreateDragDetails(point_in_parent, window_component, source); |
74 const int parent_shell_window_id = | 77 const int parent_shell_window_id = |
75 window->GetParent() ? window->GetParent()->aura_window()->id() : -1; | 78 window->parent() ? window->parent()->id() : -1; |
76 if (window->GetParent() && | 79 if (window->parent() && |
77 (parent_shell_window_id == kShellWindowId_DefaultContainer || | 80 (parent_shell_window_id == kShellWindowId_DefaultContainer || |
78 parent_shell_window_id == kShellWindowId_PanelContainer)) { | 81 parent_shell_window_id == kShellWindowId_PanelContainer)) { |
79 window_resizer.reset( | 82 window_resizer.reset(WorkspaceWindowResizer::Create( |
80 WorkspaceWindowResizer::Create(window_state, std::vector<WmWindow*>())); | 83 window_state, std::vector<aura::Window*>())); |
81 } else { | 84 } else { |
82 window_resizer.reset(DefaultWindowResizer::Create(window_state)); | 85 window_resizer.reset(DefaultWindowResizer::Create(window_state)); |
83 } | 86 } |
84 window_resizer = ShellPort::Get()->CreateDragWindowResizer( | 87 window_resizer = ShellPort::Get()->CreateDragWindowResizer( |
85 std::move(window_resizer), window_state); | 88 std::move(window_resizer), window_state); |
86 if (window->GetType() == ui::wm::WINDOW_TYPE_PANEL) { | 89 if (window->type() == ui::wm::WINDOW_TYPE_PANEL) { |
87 window_resizer.reset( | 90 window_resizer.reset( |
88 PanelWindowResizer::Create(window_resizer.release(), window_state)); | 91 PanelWindowResizer::Create(window_resizer.release(), window_state)); |
89 } | 92 } |
90 return window_resizer; | 93 return window_resizer; |
91 } | 94 } |
92 | 95 |
93 namespace { | 96 namespace { |
94 | 97 |
95 // Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset | 98 // Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset |
96 // when resizing a window using touchscreen. | 99 // when resizing a window using touchscreen. |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 if (did_lock_cursor_) | 310 if (did_lock_cursor_) |
308 ShellPort::Get()->UnlockCursor(); | 311 ShellPort::Get()->UnlockCursor(); |
309 | 312 |
310 if (instance == this) | 313 if (instance == this) |
311 instance = NULL; | 314 instance = NULL; |
312 } | 315 } |
313 | 316 |
314 // static | 317 // static |
315 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( | 318 WorkspaceWindowResizer* WorkspaceWindowResizer::Create( |
316 wm::WindowState* window_state, | 319 wm::WindowState* window_state, |
317 const std::vector<WmWindow*>& attached_windows) { | 320 const std::vector<aura::Window*>& attached_windows) { |
318 return new WorkspaceWindowResizer(window_state, attached_windows); | 321 return new WorkspaceWindowResizer(window_state, attached_windows); |
319 } | 322 } |
320 | 323 |
321 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, | 324 void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, |
322 int event_flags) { | 325 int event_flags) { |
323 last_mouse_location_ = location_in_parent; | 326 last_mouse_location_ = location_in_parent; |
324 | 327 |
325 int sticky_size; | 328 int sticky_size; |
326 if (event_flags & ui::EF_CONTROL_DOWN) { | 329 if (event_flags & ui::EF_CONTROL_DOWN) { |
327 sticky_size = 0; | 330 sticky_size = 0; |
328 } else if ((details().bounds_change & kBoundsChange_Resizes) && | 331 } else if ((details().bounds_change & kBoundsChange_Resizes) && |
329 details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 332 details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
330 sticky_size = kScreenEdgeInsetForTouchDrag; | 333 sticky_size = kScreenEdgeInsetForTouchDrag; |
331 } else { | 334 } else { |
332 sticky_size = kScreenEdgeInset; | 335 sticky_size = kScreenEdgeInset; |
333 } | 336 } |
334 // |bounds| is in |GetTarget()->parent()|'s coordinates. | 337 // |bounds| is in |GetTarget()->parent()|'s coordinates. |
335 gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); | 338 gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); |
336 AdjustBoundsForMainWindow(sticky_size, &bounds); | 339 AdjustBoundsForMainWindow(sticky_size, &bounds); |
337 | 340 |
338 if (bounds != GetTarget()->GetBounds()) { | 341 if (bounds != GetTarget()->bounds()) { |
339 if (!did_move_or_resize_) { | 342 if (!did_move_or_resize_) { |
340 if (!details().restore_bounds.IsEmpty()) | 343 if (!details().restore_bounds.IsEmpty()) |
341 window_state()->ClearRestoreBounds(); | 344 window_state()->ClearRestoreBounds(); |
342 RestackWindows(); | 345 RestackWindows(); |
343 } | 346 } |
344 did_move_or_resize_ = true; | 347 did_move_or_resize_ = true; |
345 } | 348 } |
346 | 349 |
347 gfx::Point location_in_screen = | 350 gfx::Point location_in_screen = location_in_parent; |
348 GetTarget()->GetParent()->ConvertPointToScreen(location_in_parent); | 351 ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen); |
349 | 352 |
350 WmWindow* root = nullptr; | 353 aura::Window* root = nullptr; |
351 display::Display display = | 354 display::Display display = |
352 display::Screen::GetScreen()->GetDisplayNearestPoint(location_in_screen); | 355 display::Screen::GetScreen()->GetDisplayNearestPoint(location_in_screen); |
353 // Track the last screen that the pointer was on to keep the snap phantom | 356 // Track the last screen that the pointer was on to keep the snap phantom |
354 // window there. | 357 // window there. |
355 if (display.bounds().Contains(location_in_screen)) { | 358 if (display.bounds().Contains(location_in_screen)) { |
356 root = | 359 root = Shell::GetRootWindowControllerWithDisplayId(display.id()) |
357 Shell::GetRootWindowControllerWithDisplayId(display.id())->GetWindow(); | 360 ->GetRootWindow(); |
358 } | 361 } |
359 if (!attached_windows_.empty()) | 362 if (!attached_windows_.empty()) |
360 LayoutAttachedWindows(&bounds); | 363 LayoutAttachedWindows(&bounds); |
361 if (bounds != GetTarget()->GetBounds()) { | 364 if (bounds != GetTarget()->bounds()) { |
362 // SetBounds needs to be called to update the layout which affects where the | 365 // SetBounds needs to be called to update the layout which affects where the |
363 // phantom window is drawn. Keep track if the window was destroyed during | 366 // phantom window is drawn. Keep track if the window was destroyed during |
364 // the drag and quit early if so. | 367 // the drag and quit early if so. |
365 base::WeakPtr<WorkspaceWindowResizer> resizer( | 368 base::WeakPtr<WorkspaceWindowResizer> resizer( |
366 weak_ptr_factory_.GetWeakPtr()); | 369 weak_ptr_factory_.GetWeakPtr()); |
367 GetTarget()->SetBounds(bounds); | 370 GetTarget()->SetBounds(bounds); |
368 if (!resizer) | 371 if (!resizer) |
369 return; | 372 return; |
370 } | 373 } |
371 const bool in_original_root = !root || root == GetTarget()->GetRootWindow(); | 374 const bool in_original_root = !root || root == GetTarget()->GetRootWindow(); |
(...skipping 16 matching lines...) Expand all Loading... |
388 | 391 |
389 // If the window's state type changed over the course of the drag do not snap | 392 // If the window's state type changed over the course of the drag do not snap |
390 // the window. This happens when the user minimizes or maximizes the window | 393 // the window. This happens when the user minimizes or maximizes the window |
391 // using a keyboard shortcut while dragging it. | 394 // using a keyboard shortcut while dragging it. |
392 if (window_state()->GetStateType() != details().initial_state_type) | 395 if (window_state()->GetStateType() != details().initial_state_type) |
393 return; | 396 return; |
394 | 397 |
395 bool snapped = false; | 398 bool snapped = false; |
396 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { | 399 if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) { |
397 if (!window_state()->HasRestoreBounds()) { | 400 if (!window_state()->HasRestoreBounds()) { |
398 gfx::Rect initial_bounds = GetTarget()->GetParent()->ConvertRectToScreen( | 401 gfx::Rect initial_bounds = details().initial_bounds_in_parent; |
399 details().initial_bounds_in_parent); | 402 ::wm::ConvertRectToScreen(GetTarget()->parent(), &initial_bounds); |
400 window_state()->SetRestoreBoundsInScreen( | 403 window_state()->SetRestoreBoundsInScreen( |
401 details().restore_bounds.IsEmpty() ? initial_bounds | 404 details().restore_bounds.IsEmpty() ? initial_bounds |
402 : details().restore_bounds); | 405 : details().restore_bounds); |
403 } | 406 } |
404 // TODO(oshima): Add event source type to WMEvent and move | 407 // TODO(oshima): Add event source type to WMEvent and move |
405 // metrics recording inside WindowState::OnWMEvent. | 408 // metrics recording inside WindowState::OnWMEvent. |
406 const wm::WMEvent event(snap_type_ == SNAP_LEFT ? wm::WM_EVENT_SNAP_LEFT | 409 const wm::WMEvent event(snap_type_ == SNAP_LEFT ? wm::WM_EVENT_SNAP_LEFT |
407 : wm::WM_EVENT_SNAP_RIGHT); | 410 : wm::WM_EVENT_SNAP_RIGHT); |
408 window_state()->OnWMEvent(&event); | 411 window_state()->OnWMEvent(&event); |
409 ShellPort::Get()->RecordUserMetricsAction(snap_type_ == SNAP_LEFT | 412 ShellPort::Get()->RecordUserMetricsAction(snap_type_ == SNAP_LEFT |
410 ? UMA_DRAG_MAXIMIZE_LEFT | 413 ? UMA_DRAG_MAXIMIZE_LEFT |
411 : UMA_DRAG_MAXIMIZE_RIGHT); | 414 : UMA_DRAG_MAXIMIZE_RIGHT); |
412 snapped = true; | 415 snapped = true; |
413 } | 416 } |
414 | 417 |
415 if (!snapped) { | 418 if (!snapped) { |
416 if (window_state()->IsSnapped()) { | 419 if (window_state()->IsSnapped()) { |
417 // Keep the window snapped if the user resizes the window such that the | 420 // Keep the window snapped if the user resizes the window such that the |
418 // window has valid bounds for a snapped window. Always unsnap the window | 421 // window has valid bounds for a snapped window. Always unsnap the window |
419 // if the user dragged the window via the caption area because doing this | 422 // if the user dragged the window via the caption area because doing this |
420 // is slightly less confusing. | 423 // is slightly less confusing. |
421 if (details().window_component == HTCAPTION || | 424 if (details().window_component == HTCAPTION || |
422 !AreBoundsValidSnappedBounds(window_state()->GetStateType(), | 425 !AreBoundsValidSnappedBounds(window_state()->GetStateType(), |
423 GetTarget()->GetBounds())) { | 426 GetTarget()->bounds())) { |
424 // Set the window to WINDOW_STATE_TYPE_NORMAL but keep the | 427 // Set the window to WINDOW_STATE_TYPE_NORMAL but keep the |
425 // window at the bounds that the user has moved/resized the | 428 // window at the bounds that the user has moved/resized the |
426 // window to. | 429 // window to. |
427 window_state()->SaveCurrentBoundsForRestore(); | 430 window_state()->SaveCurrentBoundsForRestore(); |
428 window_state()->Restore(); | 431 window_state()->Restore(); |
429 } | 432 } |
430 } else { | 433 } else { |
431 // The window was not snapped and is not snapped. This is a user | 434 // The window was not snapped and is not snapped. This is a user |
432 // resize/drag and so the current bounds should be maintained, clearing | 435 // resize/drag and so the current bounds should be maintained, clearing |
433 // any prior restore bounds. | 436 // any prior restore bounds. |
434 window_state()->ClearRestoreBounds(); | 437 window_state()->ClearRestoreBounds(); |
435 } | 438 } |
436 } | 439 } |
437 } | 440 } |
438 | 441 |
439 void WorkspaceWindowResizer::RevertDrag() { | 442 void WorkspaceWindowResizer::RevertDrag() { |
440 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); | 443 window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); |
441 snap_phantom_window_controller_.reset(); | 444 snap_phantom_window_controller_.reset(); |
442 | 445 |
443 if (!did_move_or_resize_) | 446 if (!did_move_or_resize_) |
444 return; | 447 return; |
445 | 448 |
446 GetTarget()->SetBounds(details().initial_bounds_in_parent); | 449 GetTarget()->SetBounds(details().initial_bounds_in_parent); |
447 if (!details().restore_bounds.IsEmpty()) | 450 if (!details().restore_bounds.IsEmpty()) |
448 window_state()->SetRestoreBoundsInScreen(details().restore_bounds); | 451 window_state()->SetRestoreBoundsInScreen(details().restore_bounds); |
449 | 452 |
450 if (details().window_component == HTRIGHT) { | 453 if (details().window_component == HTRIGHT) { |
451 int last_x = details().initial_bounds_in_parent.right(); | 454 int last_x = details().initial_bounds_in_parent.right(); |
452 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 455 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
453 gfx::Rect bounds(attached_windows_[i]->GetBounds()); | 456 gfx::Rect bounds(attached_windows_[i]->bounds()); |
454 bounds.set_x(last_x); | 457 bounds.set_x(last_x); |
455 bounds.set_width(initial_size_[i]); | 458 bounds.set_width(initial_size_[i]); |
456 attached_windows_[i]->SetBounds(bounds); | 459 attached_windows_[i]->SetBounds(bounds); |
457 last_x = attached_windows_[i]->GetBounds().right(); | 460 last_x = attached_windows_[i]->bounds().right(); |
458 } | 461 } |
459 } else { | 462 } else { |
460 int last_y = details().initial_bounds_in_parent.bottom(); | 463 int last_y = details().initial_bounds_in_parent.bottom(); |
461 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 464 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
462 gfx::Rect bounds(attached_windows_[i]->GetBounds()); | 465 gfx::Rect bounds(attached_windows_[i]->bounds()); |
463 bounds.set_y(last_y); | 466 bounds.set_y(last_y); |
464 bounds.set_height(initial_size_[i]); | 467 bounds.set_height(initial_size_[i]); |
465 attached_windows_[i]->SetBounds(bounds); | 468 attached_windows_[i]->SetBounds(bounds); |
466 last_y = attached_windows_[i]->GetBounds().bottom(); | 469 last_y = attached_windows_[i]->bounds().bottom(); |
467 } | 470 } |
468 } | 471 } |
469 } | 472 } |
470 | 473 |
471 WorkspaceWindowResizer::WorkspaceWindowResizer( | 474 WorkspaceWindowResizer::WorkspaceWindowResizer( |
472 wm::WindowState* window_state, | 475 wm::WindowState* window_state, |
473 const std::vector<WmWindow*>& attached_windows) | 476 const std::vector<aura::Window*>& attached_windows) |
474 : WindowResizer(window_state), | 477 : WindowResizer(window_state), |
475 attached_windows_(attached_windows), | 478 attached_windows_(attached_windows), |
476 did_lock_cursor_(false), | 479 did_lock_cursor_(false), |
477 did_move_or_resize_(false), | 480 did_move_or_resize_(false), |
478 initial_bounds_changed_by_user_(window_state_->bounds_changed_by_user()), | 481 initial_bounds_changed_by_user_(window_state_->bounds_changed_by_user()), |
479 total_min_(0), | 482 total_min_(0), |
480 total_initial_size_(0), | 483 total_initial_size_(0), |
481 snap_type_(SNAP_NONE), | 484 snap_type_(SNAP_NONE), |
482 num_mouse_moves_since_bounds_change_(0), | 485 num_mouse_moves_since_bounds_change_(0), |
483 magnetism_window_(NULL), | 486 magnetism_window_(NULL), |
484 weak_ptr_factory_(this) { | 487 weak_ptr_factory_(this) { |
485 DCHECK(details().is_resizable); | 488 DCHECK(details().is_resizable); |
486 | 489 |
487 // A mousemove should still show the cursor even if the window is | 490 // A mousemove should still show the cursor even if the window is |
488 // being moved or resized with touch, so do not lock the cursor. | 491 // being moved or resized with touch, so do not lock the cursor. |
489 if (details().source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 492 if (details().source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
490 ShellPort::Get()->LockCursor(); | 493 ShellPort::Get()->LockCursor(); |
491 did_lock_cursor_ = true; | 494 did_lock_cursor_ = true; |
492 } | 495 } |
493 | 496 |
494 // Only support attaching to the right/bottom. | 497 // Only support attaching to the right/bottom. |
495 DCHECK(attached_windows_.empty() || (details().window_component == HTRIGHT || | 498 DCHECK(attached_windows_.empty() || (details().window_component == HTRIGHT || |
496 details().window_component == HTBOTTOM)); | 499 details().window_component == HTBOTTOM)); |
497 | 500 |
498 // TODO: figure out how to deal with window going off the edge. | 501 // TODO: figure out how to deal with window going off the edge. |
499 | 502 |
500 // Calculate sizes so that we can maintain the ratios if we need to resize. | 503 // Calculate sizes so that we can maintain the ratios if we need to resize. |
501 int total_available = 0; | 504 int total_available = 0; |
502 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 505 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
503 gfx::Size min(attached_windows_[i]->GetMinimumSize()); | 506 gfx::Size min(attached_windows_[i]->delegate() |
504 int initial_size = | 507 ? attached_windows_[i]->delegate()->GetMinimumSize() |
505 PrimaryAxisSize(attached_windows_[i]->GetBounds().size()); | 508 : gfx::Size()); |
| 509 int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); |
506 initial_size_.push_back(initial_size); | 510 initial_size_.push_back(initial_size); |
507 // If current size is smaller than the min, use the current size as the min. | 511 // If current size is smaller than the min, use the current size as the min. |
508 // This way we don't snap on resize. | 512 // This way we don't snap on resize. |
509 int min_size = std::min(initial_size, | 513 int min_size = std::min(initial_size, |
510 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); | 514 std::max(PrimaryAxisSize(min), kMinOnscreenSize)); |
511 total_min_ += min_size; | 515 total_min_ += min_size; |
512 total_initial_size_ += initial_size; | 516 total_initial_size_ += initial_size; |
513 total_available += std::max(min_size, initial_size) - min_size; | 517 total_available += std::max(min_size, initial_size) - min_size; |
514 } | 518 } |
515 instance = this; | 519 instance = this; |
516 } | 520 } |
517 | 521 |
518 void WorkspaceWindowResizer::LayoutAttachedWindows(gfx::Rect* bounds) { | 522 void WorkspaceWindowResizer::LayoutAttachedWindows(gfx::Rect* bounds) { |
519 gfx::Rect work_area( | 523 gfx::Rect work_area( |
520 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget()->aura_window())); | 524 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget())); |
521 int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size()); | 525 int initial_size = PrimaryAxisSize(details().initial_bounds_in_parent.size()); |
522 int current_size = PrimaryAxisSize(bounds->size()); | 526 int current_size = PrimaryAxisSize(bounds->size()); |
523 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); | 527 int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); |
524 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); | 528 int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); |
525 | 529 |
526 int delta = current_size - initial_size; | 530 int delta = current_size - initial_size; |
527 int available_size = end - start; | 531 int available_size = end - start; |
528 std::vector<int> sizes; | 532 std::vector<int> sizes; |
529 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); | 533 int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); |
530 | 534 |
531 // leftovers > 0 means that the attached windows can't grow to compensate for | 535 // leftovers > 0 means that the attached windows can't grow to compensate for |
532 // the shrinkage of the main window. This line causes the attached windows to | 536 // the shrinkage of the main window. This line causes the attached windows to |
533 // be moved so they are still flush against the main window, rather than the | 537 // be moved so they are still flush against the main window, rather than the |
534 // main window being prevented from shrinking. | 538 // main window being prevented from shrinking. |
535 leftovers = std::min(0, leftovers); | 539 leftovers = std::min(0, leftovers); |
536 // Reallocate any leftover pixels back into the main window. This is | 540 // Reallocate any leftover pixels back into the main window. This is |
537 // necessary when, for example, the main window shrinks, but none of the | 541 // necessary when, for example, the main window shrinks, but none of the |
538 // attached windows can grow without exceeding their max size constraints. | 542 // attached windows can grow without exceeding their max size constraints. |
539 // Adding the pixels back to the main window effectively prevents the main | 543 // Adding the pixels back to the main window effectively prevents the main |
540 // window from resizing too far. | 544 // window from resizing too far. |
541 if (details().window_component == HTRIGHT) | 545 if (details().window_component == HTRIGHT) |
542 bounds->set_width(bounds->width() + leftovers); | 546 bounds->set_width(bounds->width() + leftovers); |
543 else | 547 else |
544 bounds->set_height(bounds->height() + leftovers); | 548 bounds->set_height(bounds->height() + leftovers); |
545 | 549 |
546 DCHECK_EQ(attached_windows_.size(), sizes.size()); | 550 DCHECK_EQ(attached_windows_.size(), sizes.size()); |
547 int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); | 551 int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); |
548 for (size_t i = 0; i < attached_windows_.size(); ++i) { | 552 for (size_t i = 0; i < attached_windows_.size(); ++i) { |
549 gfx::Rect attached_bounds(attached_windows_[i]->GetBounds()); | 553 gfx::Rect attached_bounds(attached_windows_[i]->bounds()); |
550 if (details().window_component == HTRIGHT) { | 554 if (details().window_component == HTRIGHT) { |
551 attached_bounds.set_x(last); | 555 attached_bounds.set_x(last); |
552 attached_bounds.set_width(sizes[i]); | 556 attached_bounds.set_width(sizes[i]); |
553 } else { | 557 } else { |
554 attached_bounds.set_y(last); | 558 attached_bounds.set_y(last); |
555 attached_bounds.set_height(sizes[i]); | 559 attached_bounds.set_height(sizes[i]); |
556 } | 560 } |
557 attached_windows_[i]->SetBounds(attached_bounds); | 561 attached_windows_[i]->SetBounds(attached_bounds); |
558 last += sizes[i]; | 562 last += sizes[i]; |
559 } | 563 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 total_value += sizes[i]->size(); | 642 total_value += sizes[i]->size(); |
639 | 643 |
640 for (size_t i = 0; i < sizes.size(); ++i) | 644 for (size_t i = 0; i < sizes.size(); ++i) |
641 out_ratios->push_back((static_cast<float>(sizes[i]->size())) / total_value); | 645 out_ratios->push_back((static_cast<float>(sizes[i]->size())) / total_value); |
642 } | 646 } |
643 | 647 |
644 void WorkspaceWindowResizer::CreateBucketsForAttached( | 648 void WorkspaceWindowResizer::CreateBucketsForAttached( |
645 std::vector<WindowSize>* sizes) const { | 649 std::vector<WindowSize>* sizes) const { |
646 for (size_t i = 0; i < attached_windows_.size(); i++) { | 650 for (size_t i = 0; i < attached_windows_.size(); i++) { |
647 int initial_size = initial_size_[i]; | 651 int initial_size = initial_size_[i]; |
648 int min = PrimaryAxisSize(attached_windows_[i]->GetMinimumSize()); | 652 aura::WindowDelegate* window_delegate = attached_windows_[i]->delegate(); |
649 int max = PrimaryAxisSize(attached_windows_[i]->GetMaximumSize()); | 653 int min = PrimaryAxisSize( |
| 654 window_delegate ? window_delegate->GetMinimumSize() : gfx::Size()); |
| 655 int max = PrimaryAxisSize( |
| 656 window_delegate ? window_delegate->GetMaximumSize() : gfx::Size()); |
650 | 657 |
651 sizes->push_back(WindowSize(initial_size, min, max)); | 658 sizes->push_back(WindowSize(initial_size, min, max)); |
652 } | 659 } |
653 } | 660 } |
654 | 661 |
655 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { | 662 void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { |
656 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { | 663 if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { |
| 664 gfx::Rect bounds_in_screen = *bounds; |
| 665 ::wm::ConvertRectToScreen(GetTarget()->parent(), &bounds_in_screen); |
657 gfx::Point point = OriginForMagneticAttach( | 666 gfx::Point point = OriginForMagneticAttach( |
658 GetTarget()->GetParent()->ConvertRectToScreen(*bounds), | 667 bounds_in_screen, magnetism_window_->GetBoundsInScreen(), |
659 magnetism_window_->GetBoundsInScreen(), magnetism_edge_); | 668 magnetism_edge_); |
660 point = GetTarget()->GetParent()->ConvertPointFromScreen(point); | 669 ::wm::ConvertPointFromScreen(GetTarget()->parent(), &point); |
661 bounds->set_origin(point); | 670 bounds->set_origin(point); |
662 } | 671 } |
663 } | 672 } |
664 | 673 |
665 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( | 674 void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( |
666 gfx::Rect* bounds) { | 675 gfx::Rect* bounds) { |
667 const uint32_t edges = | 676 const uint32_t edges = |
668 WindowComponentToMagneticEdge(details().window_component); | 677 WindowComponentToMagneticEdge(details().window_component); |
669 if (UpdateMagnetismWindow(*bounds, edges)) { | 678 if (UpdateMagnetismWindow(*bounds, edges)) { |
670 *bounds = GetTarget()->GetParent()->ConvertRectFromScreen( | 679 gfx::Rect bounds_in_screen = *bounds; |
671 BoundsForMagneticResizeAttach( | 680 ::wm::ConvertRectToScreen(GetTarget()->parent(), &bounds_in_screen); |
672 GetTarget()->GetParent()->ConvertRectToScreen(*bounds), | 681 *bounds = BoundsForMagneticResizeAttach( |
673 magnetism_window_->GetBoundsInScreen(), magnetism_edge_)); | 682 bounds_in_screen, magnetism_window_->GetBoundsInScreen(), |
| 683 magnetism_edge_); |
| 684 ::wm::ConvertRectFromScreen(GetTarget()->parent(), bounds); |
674 } | 685 } |
675 } | 686 } |
676 | 687 |
677 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, | 688 bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, |
678 uint32_t edges) { | 689 uint32_t edges) { |
679 // |bounds| are in coordinates of original window's parent. | 690 // |bounds| are in coordinates of original window's parent. |
680 gfx::Rect bounds_in_screen = | 691 gfx::Rect bounds_in_screen = bounds; |
681 GetTarget()->GetParent()->ConvertRectToScreen(bounds); | 692 ::wm::ConvertRectToScreen(GetTarget()->parent(), &bounds_in_screen); |
682 MagnetismMatcher matcher(bounds_in_screen, edges); | 693 MagnetismMatcher matcher(bounds_in_screen, edges); |
683 | 694 |
684 // If we snapped to a window then check it first. That way we don't bounce | 695 // If we snapped to a window then check it first. That way we don't bounce |
685 // around when close to multiple edges. | 696 // around when close to multiple edges. |
686 if (magnetism_window_) { | 697 if (magnetism_window_) { |
687 if (window_tracker_.Contains(magnetism_window_->aura_window()) && | 698 if (window_tracker_.Contains(magnetism_window_) && |
688 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), | 699 matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), |
689 &magnetism_edge_)) { | 700 &magnetism_edge_)) { |
690 return true; | 701 return true; |
691 } | 702 } |
692 window_tracker_.Remove(magnetism_window_->aura_window()); | 703 window_tracker_.Remove(magnetism_window_); |
693 magnetism_window_ = NULL; | 704 magnetism_window_ = NULL; |
694 } | 705 } |
695 | 706 |
696 // Avoid magnetically snapping windows that are not resizable. | 707 // Avoid magnetically snapping windows that are not resizable. |
697 // TODO(oshima): change this to window.type() == TYPE_NORMAL. | 708 // TODO(oshima): change this to window.type() == TYPE_NORMAL. |
698 if (!window_state()->CanResize()) | 709 if (!window_state()->CanResize()) |
699 return false; | 710 return false; |
700 | 711 |
701 for (WmWindow* root_window : ShellPort::Get()->GetAllRootWindows()) { | 712 for (aura::Window* root_window : Shell::Get()->GetAllRootWindows()) { |
702 // Test all children from the desktop in each root window. | 713 // Test all children from the desktop in each root window. |
703 const std::vector<WmWindow*> children = | 714 const std::vector<aura::Window*>& children = |
704 root_window->GetChildByShellWindowId(kShellWindowId_DefaultContainer) | 715 root_window->GetChildById(kShellWindowId_DefaultContainer)->children(); |
705 ->GetChildren(); | |
706 for (auto i = children.rbegin(); | 716 for (auto i = children.rbegin(); |
707 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { | 717 i != children.rend() && !matcher.AreEdgesObscured(); ++i) { |
708 wm::WindowState* other_state = (*i)->GetWindowState(); | 718 wm::WindowState* other_state = wm::GetWindowState(*i); |
709 if (other_state->window() == GetTarget() || | 719 if (other_state->window()->aura_window() == GetTarget() || |
710 !other_state->window()->IsVisible() || | 720 !other_state->window()->IsVisible() || |
711 !other_state->IsNormalOrSnapped() || !other_state->CanResize()) { | 721 !other_state->IsNormalOrSnapped() || !other_state->CanResize()) { |
712 continue; | 722 continue; |
713 } | 723 } |
714 if (matcher.ShouldAttach(other_state->window()->GetBoundsInScreen(), | 724 if (matcher.ShouldAttach(other_state->window()->GetBoundsInScreen(), |
715 &magnetism_edge_)) { | 725 &magnetism_edge_)) { |
716 magnetism_window_ = other_state->window(); | 726 magnetism_window_ = other_state->window()->aura_window(); |
717 window_tracker_.Add(magnetism_window_->aura_window()); | 727 window_tracker_.Add(magnetism_window_); |
718 return true; | 728 return true; |
719 } | 729 } |
720 } | 730 } |
721 } | 731 } |
722 return false; | 732 return false; |
723 } | 733 } |
724 | 734 |
725 void WorkspaceWindowResizer::AdjustBoundsForMainWindow(int sticky_size, | 735 void WorkspaceWindowResizer::AdjustBoundsForMainWindow(int sticky_size, |
726 gfx::Rect* bounds) { | 736 gfx::Rect* bounds) { |
727 gfx::Point last_mouse_location_in_screen = | 737 gfx::Point last_mouse_location_in_screen = last_mouse_location_; |
728 GetTarget()->GetParent()->ConvertPointToScreen(last_mouse_location_); | 738 ::wm::ConvertPointToScreen(GetTarget()->parent(), |
| 739 &last_mouse_location_in_screen); |
729 display::Display display = | 740 display::Display display = |
730 display::Screen::GetScreen()->GetDisplayNearestPoint( | 741 display::Screen::GetScreen()->GetDisplayNearestPoint( |
731 last_mouse_location_in_screen); | 742 last_mouse_location_in_screen); |
732 gfx::Rect work_area = | 743 gfx::Rect work_area = display.work_area(); |
733 GetTarget()->GetParent()->ConvertRectFromScreen(display.work_area()); | 744 ::wm::ConvertRectFromScreen(GetTarget()->parent(), &work_area); |
734 if (details().window_component == HTCAPTION) { | 745 if (details().window_component == HTCAPTION) { |
735 // Adjust the bounds to the work area where the mouse cursor is located. | 746 // Adjust the bounds to the work area where the mouse cursor is located. |
736 // Always keep kMinOnscreenHeight or the window height (whichever is less) | 747 // Always keep kMinOnscreenHeight or the window height (whichever is less) |
737 // on the bottom. | 748 // on the bottom. |
738 int max_y = | 749 int max_y = |
739 work_area.bottom() - std::min(kMinOnscreenHeight, bounds->height()); | 750 work_area.bottom() - std::min(kMinOnscreenHeight, bounds->height()); |
740 if (bounds->y() > max_y) { | 751 if (bounds->y() > max_y) { |
741 bounds->set_y(max_y); | 752 bounds->set_y(max_y); |
742 } else if (bounds->y() <= work_area.y()) { | 753 } else if (bounds->y() <= work_area.y()) { |
743 // Don't allow dragging above the top of the display until the mouse | 754 // Don't allow dragging above the top of the display until the mouse |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 edge_cycler_->OnMove(location); | 887 edge_cycler_->OnMove(location); |
877 } | 888 } |
878 | 889 |
879 // Update phantom window with snapped guide bounds. | 890 // Update phantom window with snapped guide bounds. |
880 const gfx::Rect phantom_bounds = | 891 const gfx::Rect phantom_bounds = |
881 (snap_type_ == SNAP_LEFT) | 892 (snap_type_ == SNAP_LEFT) |
882 ? wm::GetDefaultLeftSnappedWindowBoundsInParent(GetTarget()) | 893 ? wm::GetDefaultLeftSnappedWindowBoundsInParent(GetTarget()) |
883 : wm::GetDefaultRightSnappedWindowBoundsInParent(GetTarget()); | 894 : wm::GetDefaultRightSnappedWindowBoundsInParent(GetTarget()); |
884 | 895 |
885 if (!snap_phantom_window_controller_) { | 896 if (!snap_phantom_window_controller_) { |
886 snap_phantom_window_controller_.reset( | 897 snap_phantom_window_controller_ = |
887 new PhantomWindowController(GetTarget())); | 898 base::MakeUnique<PhantomWindowController>(WmWindow::Get(GetTarget())); |
888 } | 899 } |
889 snap_phantom_window_controller_->Show( | 900 gfx::Rect phantom_bounds_in_screen(phantom_bounds); |
890 GetTarget()->GetParent()->ConvertRectToScreen(phantom_bounds)); | 901 ::wm::ConvertRectToScreen(GetTarget()->parent(), &phantom_bounds_in_screen); |
| 902 snap_phantom_window_controller_->Show(phantom_bounds_in_screen); |
891 } | 903 } |
892 | 904 |
893 void WorkspaceWindowResizer::RestackWindows() { | 905 void WorkspaceWindowResizer::RestackWindows() { |
894 if (attached_windows_.empty()) | 906 if (attached_windows_.empty()) |
895 return; | 907 return; |
896 // Build a map from index in children to window, returning if there is a | 908 // Build a map from index in children to window, returning if there is a |
897 // window with a different parent. | 909 // window with a different parent. |
898 using IndexToWindowMap = std::map<size_t, WmWindow*>; | 910 using IndexToWindowMap = std::map<size_t, aura::Window*>; |
899 IndexToWindowMap map; | 911 IndexToWindowMap map; |
900 WmWindow* parent = GetTarget()->GetParent(); | 912 aura::Window* parent = GetTarget()->parent(); |
901 const std::vector<WmWindow*> windows(parent->GetChildren()); | 913 const std::vector<aura::Window*>& windows(parent->children()); |
902 map[std::find(windows.begin(), windows.end(), GetTarget()) - | 914 map[std::find(windows.begin(), windows.end(), GetTarget()) - |
903 windows.begin()] = GetTarget(); | 915 windows.begin()] = GetTarget(); |
904 for (auto i = attached_windows_.begin(); i != attached_windows_.end(); ++i) { | 916 for (auto i = attached_windows_.begin(); i != attached_windows_.end(); ++i) { |
905 if ((*i)->GetParent() != parent) | 917 if ((*i)->parent() != parent) |
906 return; | 918 return; |
907 size_t index = | 919 size_t index = |
908 std::find(windows.begin(), windows.end(), *i) - windows.begin(); | 920 std::find(windows.begin(), windows.end(), *i) - windows.begin(); |
909 map[index] = *i; | 921 map[index] = *i; |
910 } | 922 } |
911 | 923 |
912 // Reorder the windows starting at the topmost. | 924 // Reorder the windows starting at the topmost. |
913 parent->StackChildAtTop(map.rbegin()->second); | 925 parent->StackChildAtTop(map.rbegin()->second); |
914 for (auto i = map.rbegin(); i != map.rend();) { | 926 for (auto i = map.rbegin(); i != map.rend();) { |
915 WmWindow* window = i->second; | 927 aura::Window* window = i->second; |
916 ++i; | 928 ++i; |
917 if (i != map.rend()) | 929 if (i != map.rend()) |
918 parent->StackChildBelow(i->second, window); | 930 parent->StackChildBelow(i->second, window); |
919 } | 931 } |
920 } | 932 } |
921 | 933 |
922 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( | 934 WorkspaceWindowResizer::SnapType WorkspaceWindowResizer::GetSnapType( |
923 const gfx::Point& location) const { | 935 const gfx::Point& location) const { |
924 // TODO: this likely only wants total display area, not the area of a single | 936 // TODO: this likely only wants total display area, not the area of a single |
925 // display. | 937 // display. |
926 gfx::Rect area( | 938 gfx::Rect area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget())); |
927 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget()->aura_window())); | |
928 if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { | 939 if (details().source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { |
929 // Increase tolerance for touch-snapping near the screen edges. This is only | 940 // Increase tolerance for touch-snapping near the screen edges. This is only |
930 // necessary when the work area left or right edge is same as screen edge. | 941 // necessary when the work area left or right edge is same as screen edge. |
931 gfx::Rect display_bounds( | 942 gfx::Rect display_bounds(ScreenUtil::GetDisplayBoundsInParent(GetTarget())); |
932 ScreenUtil::GetDisplayBoundsInParent(GetTarget()->aura_window())); | |
933 int inset_left = 0; | 943 int inset_left = 0; |
934 if (area.x() == display_bounds.x()) | 944 if (area.x() == display_bounds.x()) |
935 inset_left = kScreenEdgeInsetForTouchDrag; | 945 inset_left = kScreenEdgeInsetForTouchDrag; |
936 int inset_right = 0; | 946 int inset_right = 0; |
937 if (area.right() == display_bounds.right()) | 947 if (area.right() == display_bounds.right()) |
938 inset_right = kScreenEdgeInsetForTouchDrag; | 948 inset_right = kScreenEdgeInsetForTouchDrag; |
939 area.Inset(inset_left, 0, inset_right, 0); | 949 area.Inset(inset_left, 0, inset_right, 0); |
940 } | 950 } |
941 if (location.x() <= area.x()) | 951 if (location.x() <= area.x()) |
942 return SNAP_LEFT; | 952 return SNAP_LEFT; |
943 if (location.x() >= area.right() - 1) | 953 if (location.x() >= area.right() - 1) |
944 return SNAP_RIGHT; | 954 return SNAP_RIGHT; |
945 return SNAP_NONE; | 955 return SNAP_NONE; |
946 } | 956 } |
947 | 957 |
948 bool WorkspaceWindowResizer::AreBoundsValidSnappedBounds( | 958 bool WorkspaceWindowResizer::AreBoundsValidSnappedBounds( |
949 wm::WindowStateType snapped_type, | 959 wm::WindowStateType snapped_type, |
950 const gfx::Rect& bounds_in_parent) const { | 960 const gfx::Rect& bounds_in_parent) const { |
951 DCHECK(snapped_type == wm::WINDOW_STATE_TYPE_LEFT_SNAPPED || | 961 DCHECK(snapped_type == wm::WINDOW_STATE_TYPE_LEFT_SNAPPED || |
952 snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); | 962 snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); |
953 gfx::Rect snapped_bounds = | 963 gfx::Rect snapped_bounds = |
954 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget()->aura_window()); | 964 ScreenUtil::GetDisplayWorkAreaBoundsInParent(GetTarget()); |
955 if (snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED) | 965 if (snapped_type == wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED) |
956 snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width()); | 966 snapped_bounds.set_x(snapped_bounds.right() - bounds_in_parent.width()); |
957 snapped_bounds.set_width(bounds_in_parent.width()); | 967 snapped_bounds.set_width(bounds_in_parent.width()); |
958 return bounds_in_parent == snapped_bounds; | 968 return bounds_in_parent == snapped_bounds; |
959 } | 969 } |
960 | 970 |
961 } // namespace ash | 971 } // namespace ash |
OLD | NEW |