void DesktopNotificationController::AnimateAll()

in shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.cc [183:274]


void DesktopNotificationController::AnimateAll() {
  // NOTE: This function refreshes position and size of all toasts according
  // to all current conditions. Animation time is only one of the variables
  // influencing them. Screen resolution is another.

  bool keep_animating = false;

  if (!instances_.empty()) {
    RECT work_area;
    if (SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0)) {
      ScreenMetrics metrics;
      POINT origin = {work_area.right,
                      work_area.bottom - metrics.Y(toast_margin_)};

      auto* hdwp = BeginDeferWindowPos(static_cast<int>(instances_.size()));

      for (auto&& inst : instances_) {
        if (!inst.hwnd)
          continue;

        auto* notification = Toast::Get(inst.hwnd);
        hdwp = notification->Animate(hdwp, origin);
        if (!hdwp)
          break;
        keep_animating |= notification->IsAnimationActive();
      }

      if (hdwp)
        EndDeferWindowPos(hdwp);
    }
  }

  if (!keep_animating) {
    DCHECK(hwnd_controller_);
    if (hwnd_controller_)
      KillTimer(hwnd_controller_, TimerID_Animate);
    is_animating_ = false;
  }

  // Purge dismissed notifications and collapse the stack between
  // items which are highlighted
  if (!instances_.empty()) {
    auto is_alive = [](ToastInstance& inst) {
      return inst.hwnd && IsWindowVisible(inst.hwnd);
    };

    auto is_highlighted = [](ToastInstance& inst) {
      return inst.hwnd && Toast::Get(inst.hwnd)->IsHighlighted();
    };

    for (auto it = instances_.begin();; ++it) {
      // find next highlighted item
      auto it2 = find_if(it, instances_.end(), is_highlighted);

      // collapse the stack in front of the highlighted item
      it = stable_partition(it, it2, is_alive);

      // purge the dead items
      for_each(it, it2, [this](auto&& inst) { DestroyToast(&inst); });

      if (it2 == instances_.end()) {
        instances_.erase(it, it2);
        break;
      }

      it = move(it2);
    }
  }

  // Set new toast positions
  if (!instances_.empty()) {
    ScreenMetrics metrics;
    auto margin = metrics.Y(toast_margin_);

    int target_pos = 0;
    for (auto&& inst : instances_) {
      if (inst.hwnd) {
        auto* toast = Toast::Get(inst.hwnd);

        if (toast->IsHighlighted())
          target_pos = toast->GetVerticalPosition();
        else
          toast->SetVerticalPosition(target_pos);

        target_pos += toast->GetHeight() + margin;
      }
    }
  }

  // Create new toasts from the queue
  CheckQueue();
}