window_tree_host.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/aura/window_tree_host.h"
  5. #include "base/command_line.h"
  6. #include "base/containers/contains.h"
  7. #include "base/feature_list.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/scoped_refptr.h"
  11. #include "base/metrics/field_trial_params.h"
  12. #include "base/no_destructor.h"
  13. #include "base/observer_list.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "base/time/time.h"
  16. #include "base/trace_event/trace_event.h"
  17. #include "build/build_config.h"
  18. #include "build/chromeos_buildflags.h"
  19. #include "components/viz/common/features.h"
  20. #include "components/viz/common/surfaces/frame_sink_id.h"
  21. #include "components/viz/host/host_frame_sink_manager.h"
  22. #include "ui/aura/client/capture_client.h"
  23. #include "ui/aura/client/cursor_client.h"
  24. #include "ui/aura/env.h"
  25. #include "ui/aura/host_frame_rate_throttler.h"
  26. #include "ui/aura/native_window_occlusion_tracker.h"
  27. #include "ui/aura/scoped_keyboard_hook.h"
  28. #include "ui/aura/scoped_simple_keyboard_hook.h"
  29. #include "ui/aura/window.h"
  30. #include "ui/aura/window_event_dispatcher.h"
  31. #include "ui/aura/window_targeter.h"
  32. #include "ui/aura/window_tree_host_observer.h"
  33. #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
  34. #include "ui/base/ime/init/input_method_factory.h"
  35. #include "ui/base/ime/input_method.h"
  36. #include "ui/base/layout.h"
  37. #include "ui/base/ui_base_features.h"
  38. #include "ui/base/view_prop.h"
  39. #include "ui/compositor/compositor.h"
  40. #include "ui/compositor/compositor_switches.h"
  41. #include "ui/compositor/layer.h"
  42. #include "ui/display/display.h"
  43. #include "ui/display/screen.h"
  44. #include "ui/events/keycodes/dom/dom_code.h"
  45. #include "ui/gfx/geometry/insets.h"
  46. #include "ui/gfx/geometry/point.h"
  47. #include "ui/gfx/geometry/point3_f.h"
  48. #include "ui/gfx/geometry/point_conversions.h"
  49. #include "ui/gfx/geometry/rect_conversions.h"
  50. #include "ui/gfx/geometry/size_conversions.h"
  51. #include "ui/gfx/icc_profile.h"
  52. #include "ui/gfx/switches.h"
  53. #include "ui/platform_window/platform_window_init_properties.h"
  54. namespace aura {
  55. namespace {
  56. const char kWindowTreeHostForAcceleratedWidget[] =
  57. "__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
  58. // Returns the cc::Layer used by a ui::Layer. This is a bit ugly, and is done to
  59. // avoid exposing cc::Layer outside of ui::Layer.
  60. cc::Layer* ccLayerFromUiLayer(ui::Layer* layer) {
  61. return static_cast<ui::LayerAnimationDelegate*>(layer)->GetCcLayer();
  62. }
  63. #if DCHECK_IS_ON()
  64. class ScopedLocalSurfaceIdValidator {
  65. public:
  66. explicit ScopedLocalSurfaceIdValidator(Window* window)
  67. : window_(window),
  68. local_surface_id_(window ? window->GetLocalSurfaceId()
  69. : viz::LocalSurfaceId()) {}
  70. ScopedLocalSurfaceIdValidator(const ScopedLocalSurfaceIdValidator&) = delete;
  71. ScopedLocalSurfaceIdValidator& operator=(
  72. const ScopedLocalSurfaceIdValidator&) = delete;
  73. ~ScopedLocalSurfaceIdValidator() {
  74. if (window_) {
  75. DCHECK_EQ(local_surface_id_, window_->GetLocalSurfaceId());
  76. }
  77. }
  78. private:
  79. const raw_ptr<Window> window_;
  80. const viz::LocalSurfaceId local_surface_id_;
  81. };
  82. #else
  83. class ScopedLocalSurfaceIdValidator {
  84. public:
  85. explicit ScopedLocalSurfaceIdValidator(Window* window) {}
  86. ~ScopedLocalSurfaceIdValidator() {}
  87. };
  88. #endif
  89. } // namespace
  90. // In order for viz to drop all references to resources used by the browser
  91. // (and renderers) a CompositorFrame with *no* references to other surfaces
  92. // must be generated. To do this a solid color layer is inserted into the
  93. // layer tree, and the existing root layer is removed. Adding a layer at the top
  94. // (keeping existing layer tree) is not enough, as the CompositorFrame still
  95. // contains information about the surfaces/resources that are obscured. Once the
  96. // frame is generated, the root layer (from `window_`) is inserted back in the
  97. // Compositor's root layer and then the Compositor is hidden.
  98. class WindowTreeHost::HideHelper {
  99. public:
  100. explicit HideHelper(WindowTreeHost* host)
  101. : host_(host),
  102. compositor_root_layer_(
  103. ccLayerFromUiLayer(host->window()->layer())->mutable_parent()),
  104. layer_for_transition_(
  105. std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR)) {
  106. layer_for_transition_->SetColor(SK_ColorWHITE);
  107. aura::Window* host_window = host_->window();
  108. ui::Layer* host_window_layer = host_window->layer();
  109. ui::Compositor* compositor = host_->compositor();
  110. // SetRootLayer() resets the `compositor_` member in Layer. If
  111. // SetRootLayer() were used, it would mean the existing layer hierarchy
  112. // would no longer think it is in a compositor. As this state is temporary,
  113. // and purely to release resources, SetRootLayer() is not used.
  114. // We do need to disable ticking of animations since the animation code
  115. // expects that its callers ensure that any ticking animations reference
  116. // element IDs for layers that are currently in the layer tree.
  117. DCHECK_EQ(host_window_layer, compositor->root_layer());
  118. compositor->DisableAnimations();
  119. ccLayerFromUiLayer(host_window_layer)->RemoveFromParent();
  120. layer_for_transition_->SetBounds(host_window->bounds());
  121. compositor_root_layer_->AddChild(
  122. ccLayerFromUiLayer(layer_for_transition_.get()));
  123. layer_for_transition_->OnDeviceScaleFactorChanged(
  124. host_window->layer()->device_scale_factor());
  125. // Request a presentation frame. Once the frame is generated the real root
  126. // layer is added back (from the destructor).
  127. compositor->RequestPresentationTimeForNextFrame(base::BindOnce(
  128. &HideHelper::OnFramePresented, weak_ptr_factory_.GetWeakPtr()));
  129. }
  130. ~HideHelper() {
  131. ui::Layer* host_window_layer = host_->window()->layer();
  132. compositor_root_layer_->AddChild(ccLayerFromUiLayer(host_window_layer));
  133. host_window_layer->OnDeviceScaleFactorChanged(
  134. layer_for_transition_->device_scale_factor());
  135. DCHECK_EQ(host_window_layer, host_->compositor()->root_layer());
  136. host_->compositor()->EnableAnimations();
  137. }
  138. private:
  139. void OnFramePresented(const gfx::PresentationFeedback& feedback) {
  140. host_->FinishHideTransition();
  141. // WARNING: this has been deleted.
  142. }
  143. raw_ptr<WindowTreeHost, DanglingUntriaged> host_;
  144. scoped_refptr<cc::Layer> compositor_root_layer_;
  145. std::unique_ptr<ui::Layer> layer_for_transition_;
  146. base::WeakPtrFactory<HideHelper> weak_ptr_factory_{this};
  147. };
  148. WindowTreeHost::VideoCaptureLock::~VideoCaptureLock() {
  149. if (host_)
  150. host_->DecrementVideoCaptureCount();
  151. }
  152. WindowTreeHost::VideoCaptureLock::VideoCaptureLock(WindowTreeHost* host)
  153. : host_(host->GetWeakPtr()) {}
  154. ////////////////////////////////////////////////////////////////////////////////
  155. // WindowTreeHost, public:
  156. WindowTreeHost::~WindowTreeHost() {
  157. DCHECK(!compositor_) << "compositor must be destroyed before root window";
  158. }
  159. // static
  160. WindowTreeHost* WindowTreeHost::GetForAcceleratedWidget(
  161. gfx::AcceleratedWidget widget) {
  162. return reinterpret_cast<WindowTreeHost*>(
  163. ui::ViewProp::GetValue(widget, kWindowTreeHostForAcceleratedWidget));
  164. }
  165. void WindowTreeHost::InitHost() {
  166. display::Display display =
  167. display::Screen::GetScreen()->GetDisplayNearestWindow(window());
  168. device_scale_factor_ = display.device_scale_factor();
  169. UpdateRootWindowSize();
  170. InitCompositor();
  171. Env::GetInstance()->NotifyHostInitialized(this);
  172. }
  173. void WindowTreeHost::AddObserver(WindowTreeHostObserver* observer) {
  174. observers_.AddObserver(observer);
  175. }
  176. void WindowTreeHost::RemoveObserver(WindowTreeHostObserver* observer) {
  177. observers_.RemoveObserver(observer);
  178. }
  179. bool WindowTreeHost::HasObserver(const WindowTreeHostObserver* observer) const {
  180. return observers_.HasObserver(observer);
  181. }
  182. base::WeakPtr<WindowTreeHost> WindowTreeHost::GetWeakPtr() {
  183. return weak_factory_.GetWeakPtr();
  184. }
  185. gfx::Transform WindowTreeHost::GetRootTransform() const {
  186. gfx::Transform transform;
  187. transform.Scale(device_scale_factor_, device_scale_factor_);
  188. transform *= window()->layer()->transform();
  189. return transform;
  190. }
  191. void WindowTreeHost::SetRootTransform(const gfx::Transform& transform) {
  192. window()->SetTransform(transform);
  193. UpdateRootWindowSize();
  194. }
  195. gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
  196. gfx::Transform invert;
  197. gfx::Transform transform = GetRootTransform();
  198. if (!transform.GetInverse(&invert))
  199. return transform;
  200. return invert;
  201. }
  202. void WindowTreeHost::SetDisplayTransformHint(gfx::OverlayTransform transform) {
  203. if (compositor()->display_transform_hint() == transform)
  204. return;
  205. compositor()->SetDisplayTransformHint(transform);
  206. UpdateCompositorScaleAndSize(GetBoundsInPixels().size());
  207. }
  208. gfx::Transform WindowTreeHost::GetRootTransformForLocalEventCoordinates()
  209. const {
  210. return GetRootTransform();
  211. }
  212. gfx::Transform WindowTreeHost::GetInverseRootTransformForLocalEventCoordinates()
  213. const {
  214. gfx::Transform invert;
  215. gfx::Transform transform = GetRootTransformForLocalEventCoordinates();
  216. if (!transform.GetInverse(&invert))
  217. return transform;
  218. return invert;
  219. }
  220. void WindowTreeHost::UpdateCompositorScaleAndSize(
  221. const gfx::Size& new_size_in_pixels) {
  222. gfx::Rect new_bounds(new_size_in_pixels);
  223. if (compositor_->display_transform_hint() ==
  224. gfx::OVERLAY_TRANSFORM_ROTATE_90 ||
  225. compositor_->display_transform_hint() ==
  226. gfx::OVERLAY_TRANSFORM_ROTATE_270) {
  227. new_bounds.Transpose();
  228. }
  229. // Allocate a new LocalSurfaceId for the new size or scale factor.
  230. window_->AllocateLocalSurfaceId();
  231. ScopedLocalSurfaceIdValidator lsi_validator(window());
  232. compositor_->SetScaleAndSize(device_scale_factor_, new_bounds.size(),
  233. window_->GetLocalSurfaceId());
  234. }
  235. void WindowTreeHost::ConvertDIPToScreenInPixels(gfx::Point* point) const {
  236. ConvertDIPToPixels(point);
  237. gfx::Point location = GetLocationOnScreenInPixels();
  238. point->Offset(location.x(), location.y());
  239. }
  240. void WindowTreeHost::ConvertScreenInPixelsToDIP(gfx::Point* point) const {
  241. gfx::Point location = GetLocationOnScreenInPixels();
  242. point->Offset(-location.x(), -location.y());
  243. ConvertPixelsToDIP(point);
  244. }
  245. void WindowTreeHost::ConvertDIPToPixels(gfx::Point* point) const {
  246. gfx::PointF point_f{*point};
  247. ConvertDIPToPixels(&point_f);
  248. *point = gfx::ToFlooredPoint(point_f);
  249. }
  250. void WindowTreeHost::ConvertDIPToPixels(gfx::PointF* point) const {
  251. GetRootTransform().TransformPoint(point);
  252. }
  253. void WindowTreeHost::ConvertPixelsToDIP(gfx::Point* point) const {
  254. gfx::PointF point_f{*point};
  255. ConvertPixelsToDIP(&point_f);
  256. *point = gfx::ToFlooredPoint(point_f);
  257. }
  258. void WindowTreeHost::ConvertPixelsToDIP(gfx::PointF* point) const {
  259. GetInverseRootTransform().TransformPoint(point);
  260. }
  261. void WindowTreeHost::SetCursor(gfx::NativeCursor cursor) {
  262. last_cursor_ = cursor;
  263. // A lot of code seems to depend on NULL cursors actually showing an arrow,
  264. // so just pass everything along to the host.
  265. SetCursorNative(cursor);
  266. }
  267. void WindowTreeHost::OnCursorVisibilityChanged(bool show) {
  268. // Clear any existing mouse hover effects when the cursor becomes invisible.
  269. // Note we do not need to dispatch a mouse enter when the cursor becomes
  270. // visible because that can only happen in response to a mouse event, which
  271. // will trigger its own mouse enter.
  272. if (!show) {
  273. ui::EventDispatchDetails details = dispatcher()->DispatchMouseExitAtPoint(
  274. nullptr, dispatcher()->GetLastMouseLocationInRoot(),
  275. ui::EF_CURSOR_HIDE);
  276. if (details.dispatcher_destroyed)
  277. return;
  278. }
  279. OnCursorVisibilityChangedNative(show);
  280. }
  281. void WindowTreeHost::MoveCursorToLocationInDIP(
  282. const gfx::Point& location_in_dip) {
  283. gfx::Point host_location(location_in_dip);
  284. ConvertDIPToPixels(&host_location);
  285. MoveCursorToInternal(location_in_dip, host_location);
  286. }
  287. void WindowTreeHost::MoveCursorToLocationInPixels(
  288. const gfx::Point& location_in_pixels) {
  289. gfx::Point root_location(location_in_pixels);
  290. ConvertPixelsToDIP(&root_location);
  291. MoveCursorToInternal(root_location, location_in_pixels);
  292. }
  293. ui::InputMethod* WindowTreeHost::GetInputMethod() {
  294. if (!input_method_) {
  295. input_method_owned_ = ui::CreateInputMethod(this, GetAcceleratedWidget());
  296. input_method_ = input_method_owned_.get();
  297. }
  298. return input_method_;
  299. }
  300. void WindowTreeHost::SetSharedInputMethod(ui::InputMethod* input_method) {
  301. input_method_ = input_method;
  302. input_method_owned_.reset();
  303. }
  304. ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
  305. ui::KeyEvent* event) {
  306. // If dispatch to IME is already disabled we shouldn't reach here.
  307. DCHECK(!dispatcher_->should_skip_ime());
  308. dispatcher_->set_skip_ime(true);
  309. // InputMethod::DispatchKeyEvent() is called in PRE_DISPATCH phase, so event
  310. // target is reset here to avoid issues in subsequent processing phases.
  311. ui::Event::DispatcherApi(event).set_target(nullptr);
  312. // We should bypass event rewriters here as they've been tried before.
  313. ui::EventDispatchDetails dispatch_details =
  314. GetEventSink()->OnEventFromSource(event);
  315. if (!dispatch_details.dispatcher_destroyed)
  316. dispatcher_->set_skip_ime(false);
  317. return dispatch_details;
  318. }
  319. ui::EventSink* WindowTreeHost::GetEventSink() {
  320. return dispatcher_.get();
  321. }
  322. int64_t WindowTreeHost::GetDisplayId() {
  323. return display::Screen::GetScreen()->GetDisplayNearestWindow(window()).id();
  324. }
  325. void WindowTreeHost::Show() {
  326. // Ensure that compositor has been properly initialized, see InitCompositor()
  327. // and InitHost().
  328. DCHECK(compositor());
  329. DCHECK_EQ(compositor()->root_layer(), window()->layer());
  330. OnAcceleratedWidgetMadeVisible(true);
  331. ShowImpl();
  332. window()->Show();
  333. }
  334. void WindowTreeHost::Hide() {
  335. HideImpl();
  336. OnAcceleratedWidgetMadeVisible(false);
  337. }
  338. gfx::Rect WindowTreeHost::GetBoundsInDIP() const {
  339. aura::Window* root_window = const_cast<aura::Window*>(window());
  340. display::Screen* screen = display::Screen::GetScreen();
  341. gfx::Rect screen_bounds = GetBoundsInPixels();
  342. return screen->ScreenToDIPRectInWindow(root_window, screen_bounds);
  343. }
  344. gfx::Rect WindowTreeHost::GetBoundsInAcceleratedWidgetPixelCoordinates() {
  345. return gfx::Rect(GetBoundsInPixels().size());
  346. }
  347. std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents(
  348. absl::optional<base::flat_set<ui::DomCode>> dom_codes) {
  349. // TODO(joedow): Remove the simple hook class/logic once this flag is removed.
  350. if (!base::FeatureList::IsEnabled(features::kSystemKeyboardLock))
  351. return std::make_unique<ScopedSimpleKeyboardHook>(std::move(dom_codes));
  352. if (CaptureSystemKeyEventsImpl(std::move(dom_codes)))
  353. return std::make_unique<ScopedKeyboardHook>(weak_factory_.GetWeakPtr());
  354. return nullptr;
  355. }
  356. bool WindowTreeHost::ShouldSendKeyEventToIme() {
  357. return true;
  358. }
  359. bool WindowTreeHost::IsNativeWindowOcclusionEnabled() const {
  360. return native_window_occlusion_enabled_;
  361. }
  362. void WindowTreeHost::SetNativeWindowOcclusionState(
  363. Window::OcclusionState state,
  364. const SkRegion& occluded_region) {
  365. if (occlusion_state_ == state && occluded_region_ == occluded_region)
  366. return;
  367. occlusion_state_ = state;
  368. if (compositor() && accelerated_widget_made_visible_ &&
  369. NativeWindowOcclusionTracker::
  370. IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
  371. if (ShouldThrottleWhenOccluded()) {
  372. // Throttling doesn't update the visibility.
  373. if (occlusion_state_ == Window::OcclusionState::OCCLUDED)
  374. HostFrameRateThrottler::GetInstance().AddHost(this);
  375. else
  376. HostFrameRateThrottler::GetInstance().RemoveHost(this);
  377. } else {
  378. const bool visible = CalculateCompositorVisibilityFromOcclusionState();
  379. // Transitioning to hidden means the compositor state hasn't been updated
  380. // yet, but will. In this case, always route through
  381. // UpdateCompositorVisibility() to ensure state is correctly cleaned up.
  382. if (visible != compositor()->IsVisible() || is_transitioning_to_hidden())
  383. UpdateCompositorVisibility(visible);
  384. }
  385. }
  386. for (WindowTreeHostObserver& observer : observers_)
  387. observer.OnOcclusionStateChanged(this, state, occluded_region);
  388. }
  389. void WindowTreeHost::UpdateRootWindowSize() {
  390. // Validate that the LocalSurfaceId does not change.
  391. bool compositor_inited = !!compositor()->root_layer();
  392. ScopedLocalSurfaceIdValidator lsi_validator(compositor_inited ? window()
  393. : nullptr);
  394. window()->SetBounds(CalculateRootWindowBounds());
  395. }
  396. gfx::Rect WindowTreeHost::CalculateRootWindowBounds() const {
  397. return GetTransformedRootWindowBoundsFromPixelSize(
  398. GetBoundsInPixels().size());
  399. }
  400. std::unique_ptr<ScopedEnableUnadjustedMouseEvents>
  401. WindowTreeHost::RequestUnadjustedMovement() {
  402. NOTIMPLEMENTED();
  403. return nullptr;
  404. }
  405. bool WindowTreeHost::SupportsMouseLock() {
  406. return false;
  407. }
  408. void WindowTreeHost::LockMouse(Window* window) {
  409. Window* root_window = window->GetRootWindow();
  410. DCHECK(root_window);
  411. auto* cursor_client = client::GetCursorClient(root_window);
  412. if (cursor_client) {
  413. cursor_client->HideCursor();
  414. cursor_client->LockCursor();
  415. }
  416. }
  417. void WindowTreeHost::UnlockMouse(Window* window) {
  418. Window* root_window = window->GetRootWindow();
  419. DCHECK(root_window);
  420. if (window->HasCapture())
  421. window->ReleaseCapture();
  422. auto* cursor_client = client::GetCursorClient(root_window);
  423. if (cursor_client) {
  424. cursor_client->UnlockCursor();
  425. cursor_client->ShowCursor();
  426. }
  427. }
  428. std::unique_ptr<WindowTreeHost::VideoCaptureLock>
  429. WindowTreeHost::CreateVideoCaptureLock() {
  430. if (!NativeWindowOcclusionTracker::
  431. IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
  432. return nullptr;
  433. }
  434. // Throtting doesn't actually change the visibility, so no need for the lock.
  435. if (ShouldThrottleWhenOccluded())
  436. return nullptr;
  437. ++video_capture_count_;
  438. MaybeUpdateComposibleVisibilityForVideoLockCountChange();
  439. // WrapUnique() is used as constructor is private.
  440. return base::WrapUnique(new VideoCaptureLock(this));
  441. }
  442. ////////////////////////////////////////////////////////////////////////////////
  443. // WindowTreeHost, protected:
  444. WindowTreeHost::WindowTreeHost(std::unique_ptr<Window> window)
  445. : window_(window.release()) { // See header for details on ownership.
  446. if (!window_)
  447. window_ = new Window(nullptr);
  448. auto display = display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
  449. device_scale_factor_ = display.device_scale_factor();
  450. #if BUILDFLAG(IS_WIN)
  451. // The feature state is necessary but not sufficient for checking if
  452. // occlusion is enabled. It may be disabled by other means (e.g., policy).
  453. native_window_occlusion_enabled_ =
  454. !base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless) &&
  455. base::FeatureList::IsEnabled(features::kCalculateNativeWinOcclusion);
  456. #endif
  457. }
  458. void WindowTreeHost::UpdateCompositorVisibility(bool visible) {
  459. if (!compositor())
  460. return;
  461. if (ShouldThrottleWhenOccluded()) {
  462. // If ShouldThrottleWhenOccluded() is true, then this function should only
  463. // be called if visibility is changed externally. In this case, assume
  464. // `occlusion_state_` is being ignored, and that throtting should be
  465. // disabled. For the most part, if ShouldThrottleWhenOccluded() is true,
  466. // the handling of occlusion changing is done in
  467. // SetNativeWindowOcclusionState().
  468. HostFrameRateThrottler::GetInstance().RemoveHost(this);
  469. }
  470. if (visible) {
  471. if (is_transitioning_to_hidden())
  472. RestoreHideTransitionState();
  473. } else {
  474. if (is_transitioning_to_hidden())
  475. return;
  476. if (ShouldReleaseResourcesWhenHidden()) {
  477. StartReleasingResourcesForHide();
  478. // Compositor visibility is changed once transition completes.
  479. return;
  480. }
  481. }
  482. compositor()->SetVisible(visible);
  483. }
  484. void WindowTreeHost::DestroyCompositor() {
  485. if (!compositor_)
  486. return;
  487. HostFrameRateThrottler::GetInstance().RemoveHost(this);
  488. // Explicitly delete the HideHelper early as it makes use of `compositor_`
  489. // and `window_`.
  490. hide_helper_.reset();
  491. compositor_->RemoveObserver(this);
  492. compositor_.reset();
  493. if (NativeWindowOcclusionTracker::
  494. IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
  495. NativeWindowOcclusionTracker::DisableNativeWindowOcclusionTracking(this);
  496. }
  497. }
  498. void WindowTreeHost::DestroyDispatcher() {
  499. Env::GetInstance()->NotifyHostDestroyed(this);
  500. delete window_;
  501. window_ = nullptr;
  502. dispatcher_.reset();
  503. // TODO(beng): this comment is no longer quite valid since this function
  504. // isn't called from WED, and WED isn't a subclass of Window. So it seems
  505. // like we could just rely on ~Window now.
  506. // Destroy child windows while we're still valid. This is also done by
  507. // ~Window, but by that time any calls to virtual methods overriden here (such
  508. // as GetRootWindow()) result in Window's implementation. By destroying here
  509. // we ensure GetRootWindow() still returns this.
  510. // window()->RemoveOrDestroyChildren();
  511. }
  512. void WindowTreeHost::OnAcceleratedWidgetMadeVisible(bool value) {
  513. if (accelerated_widget_made_visible_ == value)
  514. return;
  515. accelerated_widget_made_visible_ = value;
  516. // Always update the compositor (ignoring occlusion-state) as it is entirely
  517. // possible the occlusion-state is out of date at this point. It is expected
  518. // that the proper occlusion state is provided soon after this.
  519. UpdateCompositorVisibility(value);
  520. }
  521. void WindowTreeHost::CreateCompositor(bool force_software_compositor,
  522. bool use_external_begin_frame_control,
  523. bool enable_compositing_based_throttling,
  524. size_t memory_limit_when_visible_mb) {
  525. Env* env = Env::GetInstance();
  526. ui::ContextFactory* context_factory = env->context_factory();
  527. DCHECK(context_factory);
  528. compositor_ = std::make_unique<ui::Compositor>(
  529. context_factory->AllocateFrameSinkId(), context_factory,
  530. base::ThreadTaskRunnerHandle::Get(), ui::IsPixelCanvasRecordingEnabled(),
  531. use_external_begin_frame_control, force_software_compositor,
  532. enable_compositing_based_throttling, memory_limit_when_visible_mb);
  533. #if BUILDFLAG(IS_CHROMEOS_ASH)
  534. compositor_->AddObserver(this);
  535. #endif
  536. if (!dispatcher()) {
  537. window()->Init(ui::LAYER_NOT_DRAWN);
  538. window()->set_host(this);
  539. window()->SetName("RootWindow");
  540. dispatcher_ = std::make_unique<WindowEventDispatcher>(this);
  541. }
  542. }
  543. void WindowTreeHost::InitCompositor() {
  544. DCHECK(!compositor_->root_layer());
  545. compositor_->SetScaleAndSize(device_scale_factor_, GetBoundsInPixels().size(),
  546. window()->GetLocalSurfaceId());
  547. compositor_->SetRootLayer(window()->layer());
  548. display::Display display =
  549. display::Screen::GetScreen()->GetDisplayNearestWindow(window());
  550. compositor_->SetDisplayColorSpaces(display.color_spaces());
  551. }
  552. void WindowTreeHost::OnAcceleratedWidgetAvailable() {
  553. compositor_->SetAcceleratedWidget(GetAcceleratedWidget());
  554. prop_ = std::make_unique<ui::ViewProp>(
  555. GetAcceleratedWidget(), kWindowTreeHostForAcceleratedWidget, this);
  556. if (NativeWindowOcclusionTracker::
  557. IsNativeWindowOcclusionTrackingAlwaysEnabled(this)) {
  558. NativeWindowOcclusionTracker::EnableNativeWindowOcclusionTracking(this);
  559. }
  560. }
  561. void WindowTreeHost::OnHostMovedInPixels() {
  562. TRACE_EVENT0("ui", "WindowTreeHost::OnHostMovedInPixels");
  563. for (WindowTreeHostObserver& observer : observers_)
  564. observer.OnHostMovedInPixels(this);
  565. }
  566. void WindowTreeHost::OnHostResizedInPixels(
  567. const gfx::Size& new_size_in_pixels) {
  568. // The compositor is deleted from WM_DESTROY, but we don't delete things until
  569. // WM_NCDESTROY, and it must be possible to still get some messages between
  570. // these two.
  571. if (!compositor_)
  572. return;
  573. display::Display display =
  574. display::Screen::GetScreen()->GetDisplayNearestWindow(window());
  575. // If we don't have the actual display, don't overwrite the scale factor with
  576. // the default value. See https://crbug.com/1285476 for details.
  577. if (display.is_valid())
  578. device_scale_factor_ = display.device_scale_factor();
  579. UpdateRootWindowSize();
  580. // Passing |new_size_in_pixels| to set compositor size. It could be different
  581. // from GetBoundsInPixels() on Windows to contain extra space for window
  582. // transition animations and should be used to set compositor size instead of
  583. // GetBoundsInPixels() in such case.
  584. UpdateCompositorScaleAndSize(new_size_in_pixels);
  585. for (WindowTreeHostObserver& observer : observers_)
  586. observer.OnHostResized(this);
  587. }
  588. void WindowTreeHost::OnHostWorkspaceChanged() {
  589. for (WindowTreeHostObserver& observer : observers_)
  590. observer.OnHostWorkspaceChanged(this);
  591. }
  592. void WindowTreeHost::OnHostDisplayChanged() {
  593. if (!compositor_)
  594. return;
  595. display::Display display =
  596. display::Screen::GetScreen()->GetDisplayNearestWindow(window());
  597. compositor_->SetDisplayColorSpaces(display.color_spaces());
  598. }
  599. void WindowTreeHost::OnHostCloseRequested() {
  600. for (WindowTreeHostObserver& observer : observers_)
  601. observer.OnHostCloseRequested(this);
  602. }
  603. void WindowTreeHost::OnHostLostWindowCapture() {
  604. // It is possible for this function to be called during destruction, after the
  605. // root window has already been destroyed (e.g. when the ui::PlatformWindow is
  606. // destroyed, and during destruction, it loses capture. See more details in
  607. // http://crbug.com/770670)
  608. if (!window())
  609. return;
  610. Window* capture_window = client::GetCaptureWindow(window());
  611. if (capture_window && capture_window->GetRootWindow() == window())
  612. capture_window->ReleaseCapture();
  613. }
  614. void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display,
  615. uint32_t metrics) {
  616. if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE && compositor_ &&
  617. display.id() == GetDisplayId())
  618. compositor_->SetDisplayColorSpaces(display.color_spaces());
  619. // Chrome OS is handled in WindowTreeHostManager::OnDisplayMetricsChanged.
  620. // Chrome OS requires additional handling for the bounds that we do not need to
  621. // do for other OSes.
  622. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  623. if (metrics & DISPLAY_METRIC_DEVICE_SCALE_FACTOR &&
  624. display.id() == GetDisplayId())
  625. OnHostResizedInPixels(GetBoundsInPixels().size());
  626. #endif
  627. }
  628. gfx::Rect WindowTreeHost::GetTransformedRootWindowBoundsFromPixelSize(
  629. const gfx::Size& size_in_pixels) const {
  630. gfx::RectF new_bounds = gfx::RectF(gfx::Rect(size_in_pixels));
  631. GetInverseRootTransform().TransformRect(&new_bounds);
  632. return gfx::ToEnclosingRect(new_bounds);
  633. }
  634. void WindowTreeHost::SetNativeWindowOcclusionEnabled(bool enable) {
  635. native_window_occlusion_enabled_ = enable;
  636. // TODO(crbug.com/1051306) If enabled is false, make this
  637. // turn off native window occlusion on this window. Only Windows has
  638. // native window occlusion currently.
  639. }
  640. ////////////////////////////////////////////////////////////////////////////////
  641. // WindowTreeHost, private:
  642. void WindowTreeHost::DecrementVideoCaptureCount() {
  643. DCHECK_GT(video_capture_count_, 0);
  644. --video_capture_count_;
  645. MaybeUpdateComposibleVisibilityForVideoLockCountChange();
  646. }
  647. void WindowTreeHost::MaybeUpdateComposibleVisibilityForVideoLockCountChange() {
  648. // Should only be called if the occlusion is applied to the compositor.
  649. DCHECK(!ShouldThrottleWhenOccluded());
  650. // Only need to check for changes when transitioning between lock and no lock.
  651. if (video_capture_count_ > 1 || !compositor() ||
  652. !accelerated_widget_made_visible_) {
  653. return;
  654. }
  655. const bool visible = CalculateCompositorVisibilityFromOcclusionState();
  656. if (visible != compositor()->IsVisible() || is_transitioning_to_hidden())
  657. UpdateCompositorVisibility(visible);
  658. }
  659. bool WindowTreeHost::CalculateCompositorVisibilityFromOcclusionState() const {
  660. switch (occlusion_state_) {
  661. case Window::OcclusionState::UNKNOWN:
  662. return true;
  663. case Window::OcclusionState::VISIBLE:
  664. return true;
  665. case Window::OcclusionState::OCCLUDED: {
  666. // The compositor needs to be visible when capturing video.
  667. return video_capture_count_ != 0;
  668. }
  669. case Window::OcclusionState::HIDDEN:
  670. // TODO: this should really return true if `video_capture_count_` is
  671. // not zero, but this likely needs other changes to really work (such
  672. // as on windows when an HWND is iconified it is sized to 0x0).
  673. return false;
  674. }
  675. }
  676. bool WindowTreeHost::ShouldReleaseResourcesWhenHidden() const {
  677. #if BUILDFLAG(IS_WIN)
  678. if (!base::FeatureList::IsEnabled(
  679. features::kApplyNativeOcclusionToCompositor) ||
  680. !IsNativeWindowOcclusionEnabled()) {
  681. return false;
  682. }
  683. const std::string type = base::GetFieldTrialParamValueByFeature(
  684. features::kApplyNativeOcclusionToCompositor,
  685. features::kApplyNativeOcclusionToCompositorType);
  686. return type == features::kApplyNativeOcclusionToCompositorTypeRelease;
  687. #else
  688. return false;
  689. #endif
  690. }
  691. bool WindowTreeHost::ShouldThrottleWhenOccluded() const {
  692. #if BUILDFLAG(IS_WIN)
  693. if (!base::FeatureList::IsEnabled(
  694. features::kApplyNativeOcclusionToCompositor) ||
  695. !IsNativeWindowOcclusionEnabled()) {
  696. return false;
  697. }
  698. const std::string type = base::GetFieldTrialParamValueByFeature(
  699. features::kApplyNativeOcclusionToCompositor,
  700. features::kApplyNativeOcclusionToCompositorType);
  701. return type == features::kApplyNativeOcclusionToCompositorTypeThrottle;
  702. #else
  703. return false;
  704. #endif
  705. }
  706. void WindowTreeHost::RestoreHideTransitionState() {
  707. DCHECK(is_transitioning_to_hidden());
  708. hide_helper_.reset();
  709. }
  710. void WindowTreeHost::FinishHideTransition() {
  711. DCHECK(is_transitioning_to_hidden());
  712. compositor_->SetVisible(false);
  713. RestoreHideTransitionState();
  714. }
  715. // static
  716. const base::flat_set<WindowTreeHost*>&
  717. WindowTreeHost::GetThrottledHostsForTesting() {
  718. return HostFrameRateThrottler::GetInstance().hosts();
  719. }
  720. void WindowTreeHost::StartReleasingResourcesForHide() {
  721. DCHECK(!is_transitioning_to_hidden());
  722. if (compositor_->size().IsEmpty()) {
  723. // This should generally only happen during startup as Compositor silently
  724. // ignores changing the size to empty.
  725. compositor_->SetVisible(false);
  726. return;
  727. }
  728. hide_helper_ = std::make_unique<HideHelper>(this);
  729. }
  730. void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
  731. const gfx::Point& host_location) {
  732. last_cursor_request_position_in_host_ = host_location;
  733. MoveCursorToScreenLocationInPixels(host_location);
  734. client::CursorClient* cursor_client = client::GetCursorClient(window());
  735. if (cursor_client) {
  736. const display::Display& display =
  737. display::Screen::GetScreen()->GetDisplayNearestWindow(window());
  738. cursor_client->SetDisplay(display);
  739. }
  740. dispatcher()->OnCursorMovedToRootLocation(root_location);
  741. }
  742. void WindowTreeHost::OnCompositingEnded(ui::Compositor* compositor) {
  743. if (!holding_pointer_moves_)
  744. return;
  745. dispatcher_->ReleasePointerMoves();
  746. holding_pointer_moves_ = false;
  747. }
  748. void WindowTreeHost::OnCompositingChildResizing(ui::Compositor* compositor) {
  749. if (!Env::GetInstance()->throttle_input_on_resize() || holding_pointer_moves_)
  750. return;
  751. dispatcher_->HoldPointerMoves();
  752. holding_pointer_moves_ = true;
  753. }
  754. void WindowTreeHost::OnFrameSinksToThrottleUpdated(
  755. const base::flat_set<viz::FrameSinkId>& ids) {
  756. for (auto& observer : observers_)
  757. observer.OnCompositingFrameSinksToThrottleUpdated(this, ids);
  758. }
  759. } // namespace aura