Code: void ClientControlledShellSurface::OnBoundsChangeEvent(
    ash::WindowStateType current_state,
    ash::WindowStateType requested_state,
     int64_t display_id,
     const gfx::Rect& window_bounds,
     int bounds_change) {
  if (!geometry().IsEmpty() && !window_bounds.IsEmpty() &&
      (!widget_->IsMinimized() ||
       requested_state != ash::WindowStateType::kMinimized) &&
      bounds_changed_callback_) {
    ash::NonClientFrameViewAsh* frame_view = GetFrameView();

    const bool becoming_snapped =
        requested_state == ash::WindowStateType::kLeftSnapped ||
        requested_state == ash::WindowStateType::kRightSnapped;
    const bool is_tablet_mode =
        WMHelper::GetInstance()->IsTabletModeWindowManagerEnabled();
    gfx::Rect client_bounds =
        becoming_snapped && is_tablet_mode
            ? window_bounds
            : frame_view->GetClientBoundsForWindowBounds(window_bounds);
    gfx::Size current_size = frame_view->GetBoundsForClientView().size();
    bool is_resize = client_bounds.size() != current_size &&
                     !widget_->IsMaximized() && !widget_->IsFullscreen();

    bounds_changed_callback_.Run(current_state, requested_state, display_id,
                                 client_bounds, is_resize, bounds_change);

    auto* window_state = GetWindowState();
    if (server_reparent_window_ &&
        window_state->GetDisplay().id() != display_id) {
      ScopedSetBoundsLocally scoped_set_bounds(this);
      int container_id = window_state->window()->parent()->id();
      aura::Window* new_parent =
          ash::Shell::GetRootWindowControllerWithDisplayId(display_id)
              ->GetContainer(container_id);
      new_parent->AddChild(window_state->window());
    }
  }
}

Commit Message: Ignore updatePipBounds before initial bounds is set

When PIP enter/exit transition happens, window state change and
initial bounds change are committed in the same commit. However,
as state change is applied first in OnPreWidgetCommit and the
bounds is update later, if updatePipBounds is called between the
gap, it ends up returning a wrong bounds based on the previous
bounds.

Currently, there are two callstacks that end up triggering
updatePipBounds between the gap: (i) The state change causes
OnWindowAddedToLayout and updatePipBounds is called in OnWMEvent,
(ii) updatePipBounds is called in UpdatePipState to prevent it
from being placed under some system ui.

As it doesn't make sense to call updatePipBounds before the first
bounds is not set, this CL adds a boolean to defer updatePipBounds.

position.

Bug: b130782006
Test: Got VLC into PIP and confirmed it was placed at the correct
Change-Id: I5b9f3644bfb2533fd3f905bc09d49708a5d08a90
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1578719
Commit-Queue: Kazuki Takise <takise@chromium.org>
Auto-Submit: Kazuki Takise <takise@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#668724}
CWE ID: CWE-787
void ClientControlledShellSurface::OnBoundsChangeEvent(
    ash::WindowStateType current_state,
    ash::WindowStateType requested_state,
     int64_t display_id,
     const gfx::Rect& window_bounds,
     int bounds_change) {
  if (ignore_bounds_change_request_)
    return;
  if (!geometry().IsEmpty() && !window_bounds.IsEmpty() &&
      (!widget_->IsMinimized() ||
       requested_state != ash::WindowStateType::kMinimized) &&
      bounds_changed_callback_) {
    ash::NonClientFrameViewAsh* frame_view = GetFrameView();

    const bool becoming_snapped =
        requested_state == ash::WindowStateType::kLeftSnapped ||
        requested_state == ash::WindowStateType::kRightSnapped;
    const bool is_tablet_mode =
        WMHelper::GetInstance()->IsTabletModeWindowManagerEnabled();
    gfx::Rect client_bounds =
        becoming_snapped && is_tablet_mode
            ? window_bounds
            : frame_view->GetClientBoundsForWindowBounds(window_bounds);
    gfx::Size current_size = frame_view->GetBoundsForClientView().size();
    bool is_resize = client_bounds.size() != current_size &&
                     !widget_->IsMaximized() && !widget_->IsFullscreen();

    bounds_changed_callback_.Run(current_state, requested_state, display_id,
                                 client_bounds, is_resize, bounds_change);

    auto* window_state = GetWindowState();
    if (server_reparent_window_ &&
        window_state->GetDisplay().id() != display_id) {
      ScopedSetBoundsLocally scoped_set_bounds(this);
      int container_id = window_state->window()->parent()->id();
      aura::Window* new_parent =
          ash::Shell::GetRootWindowControllerWithDisplayId(display_id)
              ->GetContainer(container_id);
      new_parent->AddChild(window_state->window());
    }
  }
}
