blob: eacf5644013b66ddc817fa8a3b1bbf2d3d8fa988 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/interaction/element_tracker_widget_state.h"
#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "ui/views/widget/widget.h"
namespace views::internal {
ElementTrackerWidgetState::ElementTrackerWidgetState(Delegate& delegate,
Widget& widget)
: delegate_(&delegate), widget_(&widget) {
observation_.Observe(widget_);
visible_ = widget_->IsVisible();
minimized_ = widget_->IsMinimized();
}
ElementTrackerWidgetState::~ElementTrackerWidgetState() = default;
void ElementTrackerWidgetState::OnWidgetVisibilityChanged(Widget* widget,
bool visible) {
CancelPendingVisibilityChange();
if (visible == visible_) {
return;
}
#if !BUILDFLAG(IS_WIN)
// On all platforms but Windows, minimization comes with an automatic hide.
if (!visible && widget == widget->GetPrimaryWindowWidget()) {
// This happens *before* the minimized signal is sent, so delay processing
// until the message queue is cleared.
if (!minimized_) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
&ElementTrackerWidgetState::CommitPendingVisibilityChange,
commit_weak_ptr_factory_.GetWeakPtr()));
}
// If the window is minimized, transitions to not-visible need to be
// ignored, since the window will be artificially not-visible in this state.
return;
}
#endif
visible_ = visible;
delegate_->OnWidgetVisibilityChanged(widget, visible);
}
void ElementTrackerWidgetState::OnWidgetShowStateChanged(Widget* widget) {
CancelPendingVisibilityChange();
minimized_ = widget->IsMinimized();
}
void ElementTrackerWidgetState::OnWidgetDestroying(Widget* widget) {
CancelPendingVisibilityChange();
Delegate* delegate = delegate_;
delegate_ = nullptr;
widget_ = nullptr;
observation_.Reset();
visible_ = false;
// This has to be last since the current object could be destroyed during
// the call.
delegate->OnWidgetDestroying(widget);
}
void ElementTrackerWidgetState::CommitPendingVisibilityChange() {
if (visible_) {
visible_ = false;
delegate_->OnWidgetVisibilityChanged(widget_, false);
}
}
void ElementTrackerWidgetState::CancelPendingVisibilityChange() {
commit_weak_ptr_factory_.InvalidateWeakPtrs();
}
} // namespace views::internal