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();
}