#include "ash/capture_mode/capture_window_observer.h"
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/capture_mode/capture_mode_camera_controller.h"
#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_session.h"
#include "ash/capture_mode/capture_mode_util.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/desks/desks_util.h"
#include "ui/compositor/layer.h"
#include "ui/wm/public/activation_client.h"
namespace ash {
CaptureWindowObserver::CaptureWindowObserver(
CaptureModeSession* capture_mode_session)
: capture_mode_session_(capture_mode_session) {
Shell::Get()->activation_client()->AddObserver(this);
DesksController::Get()->AddObserver(this);
}
CaptureWindowObserver::~CaptureWindowObserver() {
DesksController::Get()->RemoveObserver(this);
Shell::Get()->activation_client()->RemoveObserver(this);
StopObserving();
}
void CaptureWindowObserver::UpdateSelectedWindowAtPosition(
const gfx::Point& location_in_screen) {
if (capture_mode_session_->IsInCountDownAnimation()) {
return;
}
location_in_screen_ = location_in_screen;
SetSelectedWindow(
capture_mode_util::GetTopMostCapturableWindowAtPoint(location_in_screen),
false,
false);
capture_mode_session_->UpdateCursor(location_in_screen, false);
}
void CaptureWindowObserver::SetSelectedWindow(aura::Window* window,
bool a11y_alert_again,
bool bar_anchored_to_window) {
if (window_ == window) {
if (a11y_alert_again && window_) {
capture_mode_session_->A11yAlertCaptureSource(true);
}
return;
}
if (window_ && bar_anchored_to_window_) {
return;
}
bar_anchored_to_window_ = bar_anchored_to_window;
if (window && window->parent() &&
window->parent()->GetId() == kShellWindowId_WallpaperContainer) {
window = nullptr;
}
if (window && window->parent() &&
window->parent()->GetId() == kShellWindowId_ShelfContainer) {
window = nullptr;
}
if (window &&
window == Shell::Get()->app_list_controller()->GetHomeScreenWindow()) {
window = nullptr;
}
StopObserving();
if (window) {
StartObserving(window);
capture_mode_session_->A11yAlertCaptureSource(true);
}
RepaintCaptureRegion();
auto* controller = CaptureModeController::Get();
if (!controller->is_recording_in_progress())
controller->camera_controller()->MaybeReparentPreviewWidget();
capture_mode_session_->MaybeUpdateCaptureUisOpacity(
display::Screen::Get()->GetCursorScreenPoint());
}
void CaptureWindowObserver::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
DCHECK_EQ(window, window_);
RepaintCaptureRegion();
auto* controller = CaptureModeController::Get();
if (!controller->is_recording_in_progress())
controller->camera_controller()->MaybeUpdatePreviewWidget();
if (bar_anchored_to_window_ &&
capture_mode_session_->GetCaptureModeBarWidget()) {
capture_mode_session_->RefreshBarWidgetBounds();
}
}
void CaptureWindowObserver::OnWindowParentChanged(aura::Window* window,
aura::Window* parent) {
if (!parent || !bar_anchored_to_window_) {
return;
}
CHECK_EQ(window, window_);
if (!desks_util::BelongsToActiveDesk(window)) {
CaptureModeController::Get()->Stop();
return;
}
capture_mode_session_->MaybeChangeRoot(window_->GetRootWindow(),
false);
RepaintCaptureRegion();
}
void CaptureWindowObserver::OnWindowVisibilityChanging(aura::Window* window,
bool visible) {
CHECK_EQ(window, window_);
CHECK(!visible);
StopObserving();
if (bar_anchored_to_window_ ||
capture_mode_session_->IsInCountDownAnimation()) {
CaptureModeController::Get()->Stop();
return;
}
UpdateSelectedWindowAtPosition(location_in_screen_);
}
void CaptureWindowObserver::OnWindowDestroying(aura::Window* window) {
CHECK_EQ(window, window_);
StopObserving();
if (bar_anchored_to_window_ ||
capture_mode_session_->IsInCountDownAnimation()) {
CaptureModeController::Get()->Stop();
return;
}
UpdateSelectedWindowAtPosition(location_in_screen_);
}
void CaptureWindowObserver::OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) {
UpdateSelectedWindowAtPosition(location_in_screen_);
}
void CaptureWindowObserver::OnDeskActivationChanged(const Desk* activated,
const Desk* deactivated) {
if (window_ && bar_anchored_to_window_ &&
!desks_util::BelongsToActiveDesk(window_)) {
CaptureModeController::Get()->Stop();
}
}
void CaptureWindowObserver::StartObserving(aura::Window* window) {
window_ = window;
window_->AddObserver(this);
}
void CaptureWindowObserver::StopObserving() {
if (window_) {
window_->RemoveObserver(this);
window_ = nullptr;
}
}
void CaptureWindowObserver::RepaintCaptureRegion() {
ui::Layer* layer = capture_mode_session_->layer();
layer->SchedulePaint(layer->bounds());
}
}