#include "ash/capture_mode/base_capture_mode_session.h"
#include "ash/accessibility/accessibility_controller.h"
#include "ash/capture_mode/capture_mode_camera_controller.h"
#include "ash/capture_mode/capture_mode_types.h"
#include "ash/capture_mode/capture_mode_util.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_item.h"
#include "ui/aura/client/capture_client.h"
#include "ui/compositor/layer.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
BaseCaptureModeSession::BaseCaptureModeSession(
CaptureModeController* controller,
CaptureModeBehavior* active_behavior,
SessionType type)
: controller_(controller),
active_behavior_(active_behavior),
session_type_(type),
current_root_(capture_mode_util::GetPreferredRootWindow()) {}
BaseCaptureModeSession::~BaseCaptureModeSession() = default;
void BaseCaptureModeSession::Initialize() {
SetLayer(std::make_unique<ui::Layer>(ui::LAYER_TEXTURED));
layer()->SetFillsBoundsOpaquely(false);
InitInternal();
MaybeUpdateSelfieCamInSessionVisibility();
if (active_behavior_->ShouldAutoSelectFirstCamera()) {
controller_->camera_controller()->MaybeSelectFirstCamera();
}
Shell::Get()->AddShellObserver(this);
active_behavior_->AttachToSession();
}
void BaseCaptureModeSession::Shutdown() {
is_shutting_down_ = true;
ShutdownInternal();
if (!is_stopping_to_start_video_recording_) {
if (!controller_->is_recording_in_progress()) {
controller_->camera_controller()->SetShouldShowPreview(false);
controller_->camera_controller()->MaybeRevertAutoCameraSelection();
}
if (controller_->type() == CaptureModeType::kVideo) {
controller_->NotifyRecordingStartAborted();
}
active_behavior_->DetachFromSession();
}
Shell::Get()->RemoveShellObserver(this);
}
aura::Window* BaseCaptureModeSession::GetOnCaptureSurfaceWidgetParentWindow()
const {
auto* controller = CaptureModeController::Get();
DCHECK(!controller->is_recording_in_progress());
auto* menu_container =
current_root_->GetChildById(kShellWindowId_MenuContainer);
auto* unparented_container =
current_root_->GetChildById(kShellWindowId_UnparentedContainer);
switch (controller->source()) {
case CaptureModeSource::kFullscreen:
return menu_container;
case CaptureModeSource::kRegion:
return controller_->user_capture_region().IsEmpty() ? unparented_container
: menu_container;
case CaptureModeSource::kWindow:
aura::Window* selected_window = GetSelectedWindow();
return selected_window ? selected_window : unparented_container;
}
}
gfx::Rect BaseCaptureModeSession::GetCaptureSurfaceConfineBounds() const {
auto* controller = CaptureModeController::Get();
DCHECK(!controller->is_recording_in_progress());
switch (controller->source()) {
case CaptureModeSource::kFullscreen: {
auto* parent = GetOnCaptureSurfaceWidgetParentWindow();
DCHECK(parent);
return display::Screen::Get()
->GetDisplayNearestWindow(parent)
.work_area();
}
case CaptureModeSource::kWindow: {
auto* selected_window = GetSelectedWindow();
return selected_window ? capture_mode_util::GetCaptureWindowConfineBounds(
selected_window)
: gfx::Rect();
}
case CaptureModeSource::kRegion: {
gfx::Rect capture_region = controller->user_capture_region();
wm::ConvertRectToScreen(current_root_, &capture_region);
return capture_region;
}
}
}
void BaseCaptureModeSession::OnRootWindowWillShutdown(
aura::Window* root_window) {
if (root_window == current_root_) {
DCHECK_NE(Shell::GetPrimaryRootWindow(), current_root_);
MaybeChangeRoot(Shell::GetPrimaryRootWindow(),
true);
}
}
aura::Window* BaseCaptureModeSession::GetParentContainer(aura::Window* root) {
DCHECK(root);
DCHECK(root->IsRootWindow());
return root->GetChildById(kShellWindowId_MenuContainer);
}
void BaseCaptureModeSession::MaybeUpdateSelfieCamInSessionVisibility() {
auto* camera_controller = controller_->camera_controller();
CHECK(camera_controller);
if (!controller_->is_recording_in_progress()) {
camera_controller->SetShouldShowPreview(controller_->type() ==
CaptureModeType::kVideo);
camera_controller->MaybeReparentPreviewWidget();
}
}
gfx::Rect BaseCaptureModeSession::GetSelectedWindowTargetBounds() const {
auto* window = GetSelectedWindow();
if (!window) {
return gfx::Rect();
}
OverviewController* overview_controller = Shell::Get()->overview_controller();
if (overview_controller->InOverviewSession()) {
if (auto* item =
overview_controller->overview_session()->GetOverviewItemForWindow(
window)) {
gfx::Rect target_bounds_in_root =
gfx::ToRoundedRect(item->target_bounds());
wm::ConvertRectFromScreen(window->GetRootWindow(),
&target_bounds_in_root);
return target_bounds_in_root;
}
}
return window->bounds();
}
}