#include "ui/aura/window_tree_host.h"
#include <optional>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/no_destructor.h"
#include "base/notimplemented.h"
#include "base/observer_list.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/host_frame_rate_throttler.h"
#include "ui/aura/native_window_occlusion_tracker.h"
#include "ui/aura/scoped_keyboard_hook.h"
#include "ui/aura/scoped_simple_keyboard_hook.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/view_prop.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/icc_profile.h"
#include "ui/gfx/switches.h"
#include "ui/platform_window/platform_window_init_properties.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
namespace aura {
namespace {
const char kWindowTreeHostForAcceleratedWidget[] =
"__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
#if DCHECK_IS_ON()
class ScopedLocalSurfaceIdValidator {
public:
explicit ScopedLocalSurfaceIdValidator(Window* window)
: window_(window),
local_surface_id_(window ? window->GetLocalSurfaceId()
: viz::LocalSurfaceId()) {}
ScopedLocalSurfaceIdValidator(const ScopedLocalSurfaceIdValidator&) = delete;
ScopedLocalSurfaceIdValidator& operator=(
const ScopedLocalSurfaceIdValidator&) = delete;
~ScopedLocalSurfaceIdValidator() {
if (window_) {
DCHECK_EQ(local_surface_id_, window_->GetLocalSurfaceId());
}
}
private:
const raw_ptr<Window> window_;
const viz::LocalSurfaceId local_surface_id_;
};
#else
class ScopedLocalSurfaceIdValidator {
public:
explicit ScopedLocalSurfaceIdValidator(Window* window) {}
~ScopedLocalSurfaceIdValidator() {}
};
#endif
}
WindowTreeHost::VideoCaptureLock::~VideoCaptureLock() {
if (host_) {
if (NativeWindowOcclusionTracker::
IsNativeWindowOcclusionTrackingAlwaysEnabled(host_.get())) {
host_->DecrementVideoCaptureCountForOcclusionTracking();
}
host_->OnVideoCaptureLockDestroyed();
}
}
WindowTreeHost::VideoCaptureLock::VideoCaptureLock(WindowTreeHost* host)
: host_(host->GetWeakPtr()) {
host_->OnVideoCaptureLockCreated();
}
const char WindowTreeHost::kWindowTreeHostUsesParent[] =
"__AURA_WINDOW_TREE_HOST_USE_PARENT_OF_ACCELERATED_WIDGET__";
WindowTreeHost::~WindowTreeHost() {
DCHECK(!compositor_) << "compositor must be destroyed before root window";
DCHECK(!base::Contains(HostFrameRateThrottler::GetInstance().hosts(), this));
}
WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
gfx::AcceleratedWidget widget) {
#if BUILDFLAG(IS_WIN)
if (ui::ViewProp::GetValue(widget, kWindowTreeHostUsesParent)) {
widget = ::GetParent(widget);
}
#endif
return reinterpret_cast<WindowTreeHost*>(
ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
}
void WindowTreeHost::InitHost() {
device_scale_factor_ = display::Screen::Get()
->GetPreferredScaleFactorForWindow(window())
.value_or(1.f);
UpdateRootWindowSize();
InitCompositor();
Env::GetInstance()->NotifyHostInitialized(this);
}
void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
observers_.AddObserver(observer);
}
void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) {
observers_.RemoveObserver(observer);
}
bool WindowTreeHost::HasObserver(const WindowTreeHostObserver* observer) const {
return observers_.HasObserver(observer);
}
base::WeakPtr<WindowTreeHost> WindowTreeHost::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
gfx::Transform WindowTreeHost::GetRootTransform() const {
gfx::Transform transform;
transform.Scale(device_scale_factor_, device_scale_factor_);
transform *= window()->layer()->transform();
return transform;
}
void WindowTreeHost::SetRootTransform(const gfx::Transform& transform) {
window()->SetTransform(transform);
UpdateRootWindowSize();
}
gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
gfx::Transform invert;
gfx::Transform transform = GetRootTransform();
if (!transform.GetInverse(&invert))
return transform;
return invert;
}
void WindowTreeHost::SetDisplayTransformHint(gfx::OverlayTransform transform) {
if (compositor()->display_transform_hint() == transform)
return;
compositor()->SetDisplayTransformHint(transform);
UpdateCompositorScaleAndSize(GetBoundsInPixels().size());
}
gfx::Transform WindowTreeHost::GetRootTransformForLocalEventCoordinates()
const {
return GetRootTransform();
}
gfx::Transform WindowTreeHost::GetInverseRootTransformForLocalEventCoordinates()
const {
gfx::Transform invert;
gfx::Transform transform = GetRootTransformForLocalEventCoordinates();
if (!transform.GetInverse(&invert))
return transform;
return invert;
}
void WindowTreeHost::UpdateCompositorScaleAndSize(
const gfx::Size& new_size_in_pixels) {
gfx::Rect new_bounds(new_size_in_pixels);
if (compositor_->display_transform_hint() ==
gfx::OVERLAY_TRANSFORM_ROTATE_CLOCKWISE_90 ||
compositor_->display_transform_hint() ==
gfx::OVERLAY_TRANSFORM_ROTATE_CLOCKWISE_270) {
new_bounds.Transpose();
}
window_->AllocateLocalSurfaceId();
ScopedLocalSurfaceIdValidator lsi_validator(window());
compositor_->SetScaleAndSize(device_scale_factor_, new_bounds.size(),
window_->GetLocalSurfaceId());
}
void WindowTreeHost::ConvertDIPToScreenInPixels(gfx::Point* point) const {
ConvertDIPToPixels(point);
gfx::Point location = GetLocationOnScreenInPixels();
point->Offset(location.x(), location.y());
}
void WindowTreeHost::ConvertScreenInPixelsToDIP(gfx::Point* point) const {
gfx::Point location = GetLocationOnScreenInPixels();
point->Offset(-location.x(), -location.y());
ConvertPixelsToDIP(point);
}
void WindowTreeHost::ConvertDIPToPixels(gfx::Point* point) const {
gfx::PointF point_f{*point};
ConvertDIPToPixels(&point_f);
*point = gfx::ToFlooredPoint(point_f);
}
void WindowTreeHost::ConvertDIPToPixels(gfx::PointF* point) const {
*point = GetRootTransform().MapPoint(*point);
}
void WindowTreeHost::ConvertPixelsToDIP(gfx::Point* point) const {
gfx::PointF point_f{*point};
ConvertPixelsToDIP(&point_f);
*point = gfx::ToFlooredPoint(point_f);
}
void WindowTreeHost::ConvertPixelsToDIP(gfx::PointF* point) const {
*point = GetInverseRootTransform().MapPoint(*point);
}
void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) {
last_cursor_ = cursor;
SetCursorNative(cursor);
}
void WindowTreeHost::OnCursorVisibilityChanged(bool show) {
if (!show) {
ui::EventDispatchDetails details = dispatcher()->DispatchMouseExitAtPoint(
nullptr, dispatcher()->GetLastMouseLocationInRoot(),
ui::EF_CURSOR_HIDE);
if (details.dispatcher_destroyed)
return;
}
OnCursorVisibilityChangedNative(show);
}
void WindowTreeHost::MoveCursorToLocationInDIP(
const gfx::Point& location_in_dip) {
gfx::Point host_location(location_in_dip);
ConvertDIPToPixels(&host_location);
MoveCursorToInternal(location_in_dip, host_location);
}
void WindowTreeHost::MoveCursorToLocationInPixels(
const gfx::Point& location_in_pixels) {
gfx::Point root_location(location_in_pixels);
ConvertPixelsToDIP(&root_location);
MoveCursorToInternal(root_location, location_in_pixels);
}
ui::InputMethod* WindowTreeHost::GetInputMethod() {
if (!input_method_) {
input_method_owned_ = ui::CreateInputMethod(this, GetAcceleratedWidget());
input_method_ = input_method_owned_.get();
}
return input_method_;
}
void WindowTreeHost::SetSharedInputMethod(ui::InputMethod* input_method) {
input_method_ = input_method;
input_method_owned_.reset();
}
ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
ui::KeyEvent* event) {
DCHECK(!dispatcher_->should_skip_ime());
dispatcher_->set_skip_ime(true);
ui::Event::DispatcherApi(event).set_target(nullptr);
ui::EventDispatchDetails dispatch_details =
GetEventSink()->OnEventFromSource(event);
if (!dispatch_details.dispatcher_destroyed)
dispatcher_->set_skip_ime(false);
return dispatch_details;
}
ui::EventSink* WindowTreeHost::GetEventSink() {
return dispatcher_.get();
}
int64_t WindowTreeHost::GetDisplayId() {
return display::Screen::Get()->GetDisplayNearestWindow(window()).id();
}
void WindowTreeHost::Show() {
DCHECK(compositor());
DCHECK_EQ(compositor()->root_layer(), window()->layer());
OnAcceleratedWidgetMadeVisible(true);
ShowImpl();
window()->Show();
}
void WindowTreeHost::Hide() {
HideImpl();
OnAcceleratedWidgetMadeVisible(false);
}
gfx::Rect WindowTreeHost::GetBoundsInDIP() const {
aura::Window* root_window = const_cast<aura::Window*>(window());
display::Screen* screen = display::Screen::Get();
gfx::Rect screen_bounds = GetBoundsInPixels();
return screen->ScreenToDIPRectInWindow(root_window, screen_bounds);
}
gfx::Rect WindowTreeHost::GetBoundsInAcceleratedWidgetPixelCoordinates() {
return gfx::Rect(GetBoundsInPixels().size());
}
std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents(
std::optional<base::flat_set<ui::DomCode>> dom_codes) {
if (!base::FeatureList::IsEnabled(features::kSystemKeyboardLock))
return std::make_unique<ScopedSimpleKeyboardHook>(std::move(dom_codes));
if (CaptureSystemKeyEventsImpl(std::move(dom_codes)))
return std::make_unique<ScopedKeyboardHook>(weak_factory_.GetWeakPtr());
return nullptr;
}
bool WindowTreeHost::ShouldSendKeyEventToIme() {
return true;
}
bool WindowTreeHost::IsNativeWindowOcclusionEnabled() const {
return native_window_occlusion_enabled_;
}
void WindowTreeHost::SetNativeWindowOcclusionState(
Window::OcclusionState raw_occlusion_state,
const SkRegion& raw_occluded_region) {
raw_occlusion_state_ = raw_occlusion_state;
raw_occluded_region_ = raw_occluded_region;
auto state = video_capture_count_for_occlusion_tracking_ > 0
? Window::OcclusionState::VISIBLE
: raw_occlusion_state;
auto occluded_region = video_capture_count_for_occlusion_tracking_ > 0
? SkRegion()
: raw_occluded_region;
if (occlusion_state_ == state && occluded_region_ == occluded_region) {
return;
}
occlusion_state_ = state;
occluded_region_ = occluded_region;
MaybeUpdateCompositorVisibilityForNativeOcclusion();
observers_.Notify(&WindowTreeHostObserver::OnOcclusionStateChanged, this,
state, occluded_region);
}
void WindowTreeHost::UpdateRootWindowSize() {
bool compositor_inited = !!compositor()->root_layer();
ScopedLocalSurfaceIdValidator lsi_validator(compositor_inited ? window()
: nullptr);
window()->SetBounds(CalculateRootWindowBounds());
}
gfx::Rect WindowTreeHost::CalculateRootWindowBounds() const {
return GetTransformedRootWindowBoundsFromPixelSize(
GetBoundsInPixels().size());
}
void WindowTreeHost::OnVideoCaptureLockCreated() {}
void WindowTreeHost::OnVideoCaptureLockDestroyed() {}
std::unique_ptr<ScopedEnableUnadjustedMouseEvents>
WindowTreeHost::RequestUnadjustedMovement() {
NOTIMPLEMENTED();
return nullptr;
}
bool WindowTreeHost::SupportsMouseLock() {
return false;
}
void WindowTreeHost::LockMouse(Window* window) {
Window* root_window = window->GetRootWindow();
DCHECK(root_window);
auto* cursor_client = client::GetCursorClient(root_window);
if (cursor_client) {
cursor_client->HideCursor();
cursor_client->LockCursor();
}
}
void WindowTreeHost::UnlockMouse(Window* window) {
Window* root_window = window->GetRootWindow();
DCHECK(root_window);
if (window->HasCapture())
window->ReleaseCapture();
auto* cursor_client = client::GetCursorClient(root_window);
if (cursor_client) {
cursor_client->UnlockCursor();
cursor_client->ShowCursor();
}
}
std::unique_ptr<WindowTreeHost::VideoCaptureLock>
WindowTreeHost::CreateVideoCaptureLock() {
if (NativeWindowOcclusionTracker::
IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
++video_capture_count_for_occlusion_tracking_;
MaybeUpdateComposibleVisibilityForVideoLockCountChange();
}
return base::WrapUnique(new VideoCaptureLock(this));
}
WindowTreeHost::WindowTreeHost(std::unique_ptr<Window> window)
: window_(window.release()) {
if (!window_) {
window_ = new Window(nullptr);
}
device_scale_factor_ = display::Screen::Get()
->GetPreferredScaleFactorForWindow(window_)
.value_or(1.f);
#if BUILDFLAG(IS_WIN)
native_window_occlusion_enabled_ =
!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless) &&
base::FeatureList::IsEnabled(features::kCalculateNativeWinOcclusion);
#endif
}
void WindowTreeHost::UpdateCompositorVisibility(bool visible) {
if (!compositor())
return;
if (NativeOcclusionAffectsThrottle()) {
HostFrameRateThrottler::GetInstance().RemoveHost(this);
}
compositor()->SetVisible(visible);
}
void WindowTreeHost::DestroyCompositor() {
if (!compositor_)
return;
HostFrameRateThrottler::GetInstance().RemoveHost(this);
compositor_->RemoveObserver(this);
compositor_.reset();
if (NativeWindowOcclusionTracker::
IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(this);
}
}
void WindowTreeHost::DestroyDispatcher() {
Env::GetInstance()->NotifyHostDestroyed(this);
delete window_;
window_ = nullptr;
dispatcher_.reset();
}
void WindowTreeHost::OnAcceleratedWidgetMadeVisible(bool value) {
if (accelerated_widget_made_visible_ == value)
return;
accelerated_widget_made_visible_ = value;
UpdateCompositorVisibility(value);
}
void WindowTreeHost::CreateCompositor(bool force_software_compositor,
bool use_external_begin_frame_control,
bool enable_compositing_based_throttling,
size_t memory_limit_when_visible_mb) {
Env* env = Env::GetInstance();
ui::ContextFactory* context_factory = env->context_factory();
DCHECK(context_factory);
compositor_ = std::make_unique<ui::Compositor>(
context_factory->AllocateFrameSinkId(), context_factory,
base::SingleThreadTaskRunner::GetCurrentDefault(),
features::IsPixelCanvasRecordingEnabled(),
use_external_begin_frame_control, force_software_compositor,
enable_compositing_based_throttling, memory_limit_when_visible_mb);
compositor_->AddObserver(this);
if (!dispatcher()) {
window()->Init(ui::LAYER_NOT_DRAWN);
window()->set_host(this);
window()->SetName("RootWindow");
dispatcher_ = std::make_unique<WindowEventDispatcher>(this);
}
}
void WindowTreeHost::InitCompositor() {
DCHECK(!compositor_->root_layer());
compositor_->SetScaleAndSize(device_scale_factor_, GetBoundsInPixels().size(),
window()->GetLocalSurfaceId());
compositor_->SetRootLayer(window()->layer());
display::Display display =
display::Screen::Get()->GetDisplayNearestWindow(window());
compositor_->SetDisplayColorSpaces(display_color_spaces_
? display_color_spaces_->color_spaces()
: display.GetColorSpaces());
}
void WindowTreeHost::OnAcceleratedWidgetAvailable() {
compositor_->SetAcceleratedWidget(GetAcceleratedWidget());
prop_ = std::make_unique<ui::ViewProp>(
GetAcceleratedWidget(), kWindowTreeHostForAcceleratedWidget, this);
if (NativeWindowOcclusionTracker::
IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
NativeWindowOcclusionTracker::EnableNativeWindowOcclusionTracking(this);
}
}
void WindowTreeHost::OnHostMovedInPixels() {
TRACE_EVENT0("ui", "WindowTreeHost::OnHostMovedInPixels");
observers_.Notify(&WindowTreeHostObserver::OnHostMovedInPixels, this);
}
void WindowTreeHost::OnHostResizedInPixels(
const gfx::Size& new_size_in_pixels) {
if (!compositor_)
return;
auto* screen = display::Screen::Get();
if (auto scale = screen->GetPreferredScaleFactorForWindow(window())) {
device_scale_factor_ = scale.value();
}
UpdateRootWindowSize();
UpdateCompositorScaleAndSize(new_size_in_pixels);
observers_.Notify(&WindowTreeHostObserver::OnHostResized, this);
}
void WindowTreeHost::OnHostWorkspaceChanged() {
observers_.Notify(&WindowTreeHostObserver::OnHostWorkspaceChanged, this);
}
void WindowTreeHost::OnHostDisplayChanged() {
if (!compositor_ || display_color_spaces_) {
return;
}
display::Display display =
display::Screen::Get()->GetDisplayNearestWindow(window());
compositor_->SetDisplayColorSpaces(display.GetColorSpaces());
}
void WindowTreeHost::OnHostCloseRequested() {
observers_.Notify(&WindowTreeHostObserver::OnHostCloseRequested, this);
}
void WindowTreeHost::OnHostLostWindowCapture() {
if (!window())
return;
Window* capture_window = client::GetCaptureWindow(window());
if (capture_window && capture_window->GetRootWindow() == window())
capture_window->ReleaseCapture();
}
void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) {
if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE && compositor_ &&
display.id() == GetDisplayId() && !display_color_spaces_) {
compositor_->SetDisplayColorSpaces(display.GetColorSpaces());
}
#if !BUILDFLAG(IS_CHROMEOS)
if (metrics & DISPLAY_METRIC_DEVICE_SCALE_FACTOR &&
display.id() == GetDisplayId())
OnHostResizedInPixels(GetBoundsInPixels().size());
#endif
}
void WindowTreeHost::OnDisplayColorSpacesChanged(
scoped_refptr<gfx::DisplayColorSpacesRef> color_spaces) {
DCHECK(color_spaces);
display_color_spaces_ = color_spaces;
if (compositor_) {
compositor_->SetDisplayColorSpaces(color_spaces->color_spaces());
}
}
gfx::Rect WindowTreeHost::GetTransformedRootWindowBoundsFromPixelSize(
const gfx::Size& size_in_pixels) const {
return GetInverseRootTransform().MapRect(gfx::Rect(size_in_pixels));
}
void WindowTreeHost::SetNativeWindowOcclusionEnabled(bool enable) {
native_window_occlusion_enabled_ = enable;
}
void WindowTreeHost::DecrementVideoCaptureCountForOcclusionTracking() {
DCHECK_GT(video_capture_count_for_occlusion_tracking_, 0);
--video_capture_count_for_occlusion_tracking_;
MaybeUpdateComposibleVisibilityForVideoLockCountChange();
}
void WindowTreeHost::MaybeUpdateComposibleVisibilityForVideoLockCountChange() {
if (video_capture_count_for_occlusion_tracking_ > 1) {
return;
}
SetNativeWindowOcclusionState(raw_occlusion_state_, raw_occluded_region_);
MaybeUpdateCompositorVisibilityForNativeOcclusion();
}
void WindowTreeHost::MaybeUpdateCompositorVisibilityForNativeOcclusion() {
if (!compositor() || !accelerated_widget_made_visible_ ||
!NativeWindowOcclusionTracker::
IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
return;
}
const bool visible = CalculateCompositorVisibilityFromOcclusionState();
if (visible != compositor()->IsVisible()) {
UpdateCompositorVisibility(visible);
}
if (NativeOcclusionAffectsThrottle()) {
if (ShouldThrottle()) {
HostFrameRateThrottler::GetInstance().AddHost(this);
} else {
HostFrameRateThrottler::GetInstance().RemoveHost(this);
}
}
}
bool WindowTreeHost::CalculateCompositorVisibilityFromOcclusionState() const {
if (!NativeOcclusionAffectsVisibility()) {
return true;
}
switch (occlusion_state_) {
case Window::OcclusionState::UNKNOWN:
return true;
case Window::OcclusionState::VISIBLE:
return true;
case Window::OcclusionState::OCCLUDED: {
return video_capture_count_for_occlusion_tracking_ != 0;
}
case Window::OcclusionState::HIDDEN:
return video_capture_count_for_occlusion_tracking_ != 0;
}
}
bool WindowTreeHost::NativeOcclusionAffectsThrottle() const {
#if BUILDFLAG(IS_WIN)
if (!base::FeatureList::IsEnabled(
features::kApplyNativeOcclusionToCompositor) ||
!IsNativeWindowOcclusionEnabled()) {
return false;
}
const std::string type =
features::kApplyNativeOcclusionToCompositorType.Get();
return type == features::kApplyNativeOcclusionToCompositorTypeThrottle ||
type ==
features::kApplyNativeOcclusionToCompositorTypeThrottleAndRelease;
#else
return false;
#endif
}
bool WindowTreeHost::NativeOcclusionAffectsVisibility() const {
#if BUILDFLAG(IS_WIN)
if (!base::FeatureList::IsEnabled(
features::kApplyNativeOcclusionToCompositor) ||
!IsNativeWindowOcclusionEnabled()) {
return false;
}
const std::string type =
features::kApplyNativeOcclusionToCompositorType.Get();
return type == features::kApplyNativeOcclusionToCompositorTypeRelease ||
type ==
features::kApplyNativeOcclusionToCompositorTypeThrottleAndRelease;
#else
return false;
#endif
}
bool WindowTreeHost::ShouldThrottle() const {
DCHECK(NativeOcclusionAffectsThrottle());
return video_capture_count_for_occlusion_tracking_ == 0 &&
occlusion_state_ == Window::OcclusionState::OCCLUDED;
}
const base::flat_set<raw_ptr<WindowTreeHost, CtnExperimental>>&
WindowTreeHost::GetThrottledHostsForTesting() {
return HostFrameRateThrottler::GetInstance().hosts();
}
void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
const gfx::Point& host_location) {
last_cursor_request_position_in_host_ = host_location;
MoveCursorToScreenLocationInPixels(host_location);
client::CursorClient* cursor_client = client::GetCursorClient(window());
if (cursor_client) {
const display::Display& display =
display::Screen::Get()->GetDisplayNearestWindow(window());
cursor_client->SetDisplay(display);
}
dispatcher()->OnCursorMovedToRootLocation(root_location);
}
void WindowTreeHost::OnCompositingAckDeprecated(ui::Compositor* compositor) {
#if BUILDFLAG(IS_CHROMEOS)
if (!holding_pointer_moves_)
return;
dispatcher_->ReleasePointerMoves();
holding_pointer_moves_ = false;
#endif
}
void WindowTreeHost::OnCompositingChildResizing(ui::Compositor* compositor) {
#if BUILDFLAG(IS_CHROMEOS)
if (!Env::GetInstance()->throttle_input_on_resize() || holding_pointer_moves_)
return;
dispatcher_->HoldPointerMoves();
holding_pointer_moves_ = true;
#endif
}
void WindowTreeHost::OnFrameSinksToThrottleUpdated(
const base::flat_set<viz::FrameSinkId>& ids) {
observers_.Notify(
&WindowTreeHostObserver::OnCompositingFrameSinksToThrottleUpdated, this,
ids);
}
void WindowTreeHost::OnSetPreferredRefreshRate(ui::Compositor*,
float preferred_refresh_rate) {
observers_.Notify(&WindowTreeHostObserver::OnSetPreferredRefreshRate, this,
preferred_refresh_rate);
}
void WindowTreeHost::OnFirstSurfaceActivation(
ui::Compositor*,
const viz::SurfaceInfo& surface_info) {
window()->UpdateLocalSurfaceIdFromEmbeddedClient(
surface_info.id().local_surface_id());
observers_.Notify(&WindowTreeHostObserver::OnLocalSurfaceIdChanged, this,
window()->GetLocalSurfaceId());
}
}