Commit 96202134 authored by Min Chen's avatar Min Chen Committed by Commit Bot

Defer resetting identity transform of the drag window from top until

it has been snapped.

We did defer resetting the transform to identity of the drag window from
overview items until it has been snapped. In order to avoid the weird
transform if trying to snap an arc window.

Previous cl:
https://chromium-review.googlesource.com/c/chromium/src/+/910076

We should do the same thing if we try to snap a window through drag from
the top.
Changes in this cl,
- Do not restore the drag window's transform to identity when end window
   drag if the window should be snapped or drop into overview.

- Restore identity transform after window has been snapped. Calculate a
  starting transform for the to-be-snapped window based on its transformed
  bounds before to be snapped.

- Move the logic of GetTransformedBounds and GetTopInset to overview_util.

Bug: 872538
Change-Id: Icc2f034e0752fba4ba8ec673022e1f9306ca35b2
Reviewed-on: https://chromium-review.googlesource.com/1178385
Commit-Queue: Min Chen <minch@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#586030}
parent 9c6ba22a
......@@ -12,13 +12,16 @@
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_transient_descendant_iterator.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "ui/aura/window.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/background.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_animations.h"
namespace ash {
......@@ -217,4 +220,37 @@ std::unique_ptr<views::Widget> CreateBackgroundWidget(aura::Window* root_window,
return widget;
}
gfx::Rect GetTransformedBounds(aura::Window* transformed_window,
int top_inset) {
gfx::Rect bounds;
for (auto* window : wm::GetTransientTreeIterator(transformed_window)) {
// Ignore other window types when computing bounding box of window
// selector target item.
if (window != transformed_window &&
(window->type() != aura::client::WINDOW_TYPE_NORMAL &&
window->type() != aura::client::WINDOW_TYPE_PANEL)) {
continue;
}
gfx::RectF window_bounds(window->GetTargetBounds());
gfx::Transform new_transform =
TransformAboutPivot(gfx::Point(window_bounds.x(), window_bounds.y()),
window->layer()->GetTargetTransform());
new_transform.TransformRect(&window_bounds);
// The preview title is shown above the preview window. Hide the window
// header for apps or browser windows with no tabs (web apps) to avoid
// showing both the window header and the preview title.
if (top_inset > 0) {
gfx::RectF header_bounds(window_bounds);
header_bounds.set_height(top_inset);
new_transform.TransformRect(&header_bounds);
window_bounds.Inset(0, gfx::ToCeiledInt(header_bounds.height()), 0, 0);
}
gfx::Rect enclosing_bounds = ToEnclosingRect(window_bounds);
::wm::ConvertRectToScreen(window->parent(), &enclosing_bounds);
bounds.Union(enclosing_bounds);
}
return bounds;
}
} // namespace ash
......@@ -11,6 +11,7 @@
#include "ash/wm/overview/overview_animation_type.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/layer_type.h"
#include "ui/gfx/geometry/rect.h"
namespace aura {
class Window;
......@@ -60,6 +61,14 @@ std::unique_ptr<views::Widget> CreateBackgroundWidget(aura::Window* root_window,
float initial_opacity,
aura::Window* parent,
bool stack_on_top);
// Calculates the bounds of the |transformed_window|. Those bounds are a union
// of all regular (normal and panel) windows in the |transformed_window|'s
// transient hierarchy. The returned Rect is in virtual screen coordinates. The
// returned bounds are adjusted to allow the original |transformed_window|'s
// header to be hidden if |top_inset| is not zero.
gfx::Rect GetTransformedBounds(aura::Window* transformed_window, int top_inset);
} // namespace ash
#endif // ASH_WM_OVERVIEW_OVERVIEW_UTILS_H_
......@@ -289,37 +289,7 @@ gfx::Rect ScopedTransformOverviewWindow::GetTargetBoundsInScreen() const {
}
gfx::Rect ScopedTransformOverviewWindow::GetTransformedBounds() const {
const int top_inset = GetTopInset();
gfx::Rect bounds;
aura::Window* overview_window = GetOverviewWindow();
for (auto* window : wm::GetTransientTreeIterator(overview_window)) {
// Ignore other window types when computing bounding box of window
// selector target item.
if (window != overview_window &&
(window->type() != aura::client::WINDOW_TYPE_NORMAL &&
window->type() != aura::client::WINDOW_TYPE_PANEL)) {
continue;
}
gfx::RectF window_bounds(window->GetTargetBounds());
gfx::Transform new_transform =
TransformAboutPivot(gfx::Point(window_bounds.x(), window_bounds.y()),
window->layer()->GetTargetTransform());
new_transform.TransformRect(&window_bounds);
// The preview title is shown above the preview window. Hide the window
// header for apps or browser windows with no tabs (web apps) to avoid
// showing both the window header and the preview title.
if (top_inset > 0) {
gfx::RectF header_bounds(window_bounds);
header_bounds.set_height(top_inset);
new_transform.TransformRect(&header_bounds);
window_bounds.Inset(0, gfx::ToCeiledInt(header_bounds.height()), 0, 0);
}
gfx::Rect enclosing_bounds = ToEnclosingRect(window_bounds);
::wm::ConvertRectToScreen(window->parent(), &enclosing_bounds);
bounds.Union(enclosing_bounds);
}
return bounds;
return ::ash::GetTransformedBounds(GetOverviewWindow(), GetTopInset());
}
int ScopedTransformOverviewWindow::GetTopInset() const {
......
......@@ -102,11 +102,8 @@ class ASH_EXPORT ScopedTransformOverviewWindow
// Returns the original target bounds of all transformed windows.
gfx::Rect GetTargetBoundsInScreen() const;
// Calculates the bounds of a |window_| after being transformed to the
// selector's space. Those bounds are a union of all regular (normal and
// panel) windows in the |window_|'s transient hierarchy. The returned Rect is
// in virtual screen coordinates. The returned bounds are adjusted to allow
// the original |window_|'s header to be hidden.
// Returns transformed bounds of the overview window. See
// OverviewUtil::GetTransformedBounds for more details.
gfx::Rect GetTransformedBounds() const;
// Returns the kTopViewInset property of |window_| unless there are transient
......
......@@ -19,6 +19,7 @@
#include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/overview/window_selector_item.h"
......@@ -266,8 +267,7 @@ void SplitViewController::SnapWindow(aura::Window* window,
DCHECK(window && CanSnap(window));
DCHECK_NE(snap_position, NONE);
// Before trying to snap |window|, try to remove it from the overview window
// grid if applicable.
UpdateSnappingWindowTransformedBounds(window);
RemoveWindowFromOverviewIfApplicable(window);
if (state_ == NO_SNAP) {
......@@ -570,7 +570,7 @@ void SplitViewController::EndSplitView(EndReason end_reason) {
black_scrim_layer_.reset();
default_snap_position_ = NONE;
divider_position_ = -1;
overview_window_item_bounds_map_.clear();
snapping_window_transformed_bounds_map_.clear();
UpdateSplitViewStateAndNotifyObservers();
base::RecordAction(base::UserMetricsAction("SplitView_EndSplitView"));
......@@ -621,9 +621,9 @@ void SplitViewController::AddObserver(mojom::SplitViewObserverPtr observer) {
void SplitViewController::OnWindowDestroyed(aura::Window* window) {
DCHECK(IsSplitViewModeActive());
DCHECK(window == left_window_ || window == right_window_);
auto iter = overview_window_item_bounds_map_.find(window);
if (iter != overview_window_item_bounds_map_.end())
overview_window_item_bounds_map_.erase(iter);
auto iter = snapping_window_transformed_bounds_map_.find(window);
if (iter != snapping_window_transformed_bounds_map_.end())
snapping_window_transformed_bounds_map_.erase(iter);
OnSnappedWindowDetached(window);
}
......@@ -1102,8 +1102,6 @@ int SplitViewController::GetDividerEndPosition() {
}
void SplitViewController::OnWindowSnapped(aura::Window* window) {
// Restore the window's transform if it's not identity. It means the window
// comes from the overview.
RestoreTransformIfApplicable(window);
UpdateSplitViewStateAndNotifyObservers();
ActivateAndStackSnappedWindow(window);
......@@ -1271,19 +1269,19 @@ gfx::Point SplitViewController::GetEndDragLocationInScreen(
void SplitViewController::RestoreTransformIfApplicable(aura::Window* window) {
DCHECK(window == left_window_ || window == right_window_);
// If the snapped window comes from the overview window grid, calculate a good
// starting transform based on the overview window item's bounds.
auto iter = overview_window_item_bounds_map_.find(window);
if (iter == overview_window_item_bounds_map_.end())
// If the transform of the window has been changed, calculate a good starting
// transform based on its transformed bounds before to be snapped.
auto iter = snapping_window_transformed_bounds_map_.find(window);
if (iter == snapping_window_transformed_bounds_map_.end())
return;
const gfx::Rect item_bounds = iter->second;
overview_window_item_bounds_map_.erase(iter);
snapping_window_transformed_bounds_map_.erase(iter);
// Restore the window's transform first if it's not identity.
if (!window->layer()->GetTargetTransform().IsIdentity()) {
// Calculate the starting transform based on the window's expected snapped
// bounds and its window item bounds in overview.
// bounds and its transformed bounds before to be snapped.
const gfx::Rect snapped_bounds = GetSnappedWindowBoundsInScreen(
window, (window == left_window_) ? LEFT : RIGHT);
const gfx::Transform starting_transform =
......@@ -1392,10 +1390,6 @@ void SplitViewController::RemoveWindowFromOverviewIfApplicable(
if (!item)
return;
// Before removing |window| from overview grid, remember its current bounds
// in the overview grid.
overview_window_item_bounds_map_[window] = item->target_bounds();
// Remove it from the grid. The transform will be reset later after the
// window is snapped. Note the remaining windows in overview don't need to be
// repositioned in this case as they have been positioned to the right place
......@@ -1404,6 +1398,14 @@ void SplitViewController::RemoveWindowFromOverviewIfApplicable(
window_selector->RemoveWindowSelectorItem(item, /*reposition=*/false);
}
void SplitViewController::UpdateSnappingWindowTransformedBounds(
aura::Window* window) {
if (!window->layer()->GetTargetTransform().IsIdentity()) {
snapping_window_transformed_bounds_map_[window] =
GetTransformedBounds(window, /*top_inset=*/0);
}
}
void SplitViewController::InsertWindowToOverview(aura::Window* window) {
if (!window || !Shell::Get()->window_selector_controller()->IsSelecting())
return;
......
......@@ -325,6 +325,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// called before trying to snap the window.
void RemoveWindowFromOverviewIfApplicable(aura::Window* window);
// Updates the |snapping_window_transformed_bounds_map_| on |window|. It
// should be called before trying to snap the window.
void UpdateSnappingWindowTransformedBounds(aura::Window* window);
// Inserts |window| into overview window grid if overview mode is active. Do
// nothing if overview mode is inactive at the moment.
void InsertWindowToOverview(aura::Window* window);
......@@ -405,9 +409,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// The time when splitview starts. Used for metric collection purpose.
base::Time splitview_start_time_;
// The map from a to-be-snapped window to its overview item's bounds if the
// window comes from the overview.
base::flat_map<aura::Window*, gfx::Rect> overview_window_item_bounds_map_;
// The map from a to-be-snapped window to its transformed bounds.
base::flat_map<aura::Window*, gfx::Rect>
snapping_window_transformed_bounds_map_;
base::ObserverList<Observer>::Unchecked observers_;
mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_;
......
......@@ -196,11 +196,15 @@ void TabletModeWindowDragDelegate::EndWindowDrag(
split_view_drag_indicators_->SetIndicatorState(IndicatorState::kNone,
location_in_screen);
// If |dragged_window_|'s transform has changed during dragging, and it has
// not been added into overview grid, restore its transform to identity.
const bool snapped_or_into_overview =
snap_position != SplitViewController::NONE ||
(GetWindowSelector() &&
GetWindowSelector()->IsWindowInOverview(dragged_window_));
// If |dragged_window_|'s transform has changed during dragging, and it was
// not snapped into splitscreen or dropped into overview. Then restore its
// transform to identity.
if (!dragged_window_->layer()->GetTargetTransform().IsIdentity() &&
(!GetWindowSelector() ||
!GetWindowSelector()->IsWindowInOverview(dragged_window_))) {
!snapped_or_into_overview) {
SetTransform(dragged_window_, gfx::Transform());
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment