window_tree_host_manager.cc 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. // Copyright (c) 2012 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 "ash/display/window_tree_host_manager.h"
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <map>
  8. #include <memory>
  9. #include <utility>
  10. #include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
  11. #include "ash/accessibility/magnifier/partial_magnifier_controller.h"
  12. #include "ash/display/cursor_window_controller.h"
  13. #include "ash/display/mirror_window_controller.h"
  14. #include "ash/display/root_window_transformers.h"
  15. #include "ash/frame_throttler/frame_throttling_controller.h"
  16. #include "ash/host/ash_window_tree_host.h"
  17. #include "ash/host/ash_window_tree_host_init_params.h"
  18. #include "ash/host/root_window_transformer.h"
  19. #include "ash/root_window_controller.h"
  20. #include "ash/root_window_settings.h"
  21. #include "ash/session/session_controller_impl.h"
  22. #include "ash/shell.h"
  23. #include "ash/system/status_area_widget.h"
  24. #include "ash/system/unified/unified_system_tray.h"
  25. #include "ash/wm/window_util.h"
  26. #include "base/bind.h"
  27. #include "base/metrics/histogram.h"
  28. #include "base/metrics/histogram_functions.h"
  29. #include "base/notreached.h"
  30. #include "base/strings/stringprintf.h"
  31. #include "base/strings/utf_string_conversions.h"
  32. #include "base/threading/thread_task_runner_handle.h"
  33. #include "ui/aura/client/capture_client.h"
  34. #include "ui/aura/client/focus_client.h"
  35. #include "ui/aura/client/screen_position_client.h"
  36. #include "ui/aura/window.h"
  37. #include "ui/aura/window_event_dispatcher.h"
  38. #include "ui/aura/window_tracker.h"
  39. #include "ui/aura/window_tree_host.h"
  40. #include "ui/base/class_property.h"
  41. #include "ui/base/ime/init/input_method_factory.h"
  42. #include "ui/base/l10n/l10n_util.h"
  43. #include "ui/base/ui_base_features.h"
  44. #include "ui/compositor/compositor.h"
  45. #include "ui/compositor/layer.h"
  46. #include "ui/display/display.h"
  47. #include "ui/display/display_features.h"
  48. #include "ui/display/display_layout.h"
  49. #include "ui/display/display_transform.h"
  50. #include "ui/display/manager/display_configurator.h"
  51. #include "ui/display/manager/display_layout_store.h"
  52. #include "ui/display/manager/display_manager.h"
  53. #include "ui/display/screen.h"
  54. #include "ui/display/types/display_constants.h"
  55. #include "ui/display/util/display_util.h"
  56. #include "ui/gfx/geometry/rounded_corners_f.h"
  57. #include "ui/wm/core/coordinate_conversion.h"
  58. #include "ui/wm/public/activation_client.h"
  59. namespace ash {
  60. namespace {
  61. // Primary display stored in global object as it can be
  62. // accessed after Shell is deleted. A separate display instance is created
  63. // during the shutdown instead of always keeping two display instances
  64. // (one here and another one in display_manager) in sync, which is error prone.
  65. // This is initialized in the constructor, and then in CreatePrimaryHost().
  66. int64_t primary_display_id = -1;
  67. // The compositor memory limit when display size is larger than a threshold.
  68. constexpr int kUICompositorLargeMemoryLimitMB = 1024;
  69. // The display size threshold, above which the larger memory limit is used.
  70. // Pixel size was chosen to trigger for 4K+ displays. See: crbug.com/1261776
  71. constexpr int kUICompositorMemoryLimitDisplaySizeThreshold = 3500;
  72. // An UMA signal for the current effective resolution is sent at this rate. This
  73. // keeps track of the effective resolution most used on internal display by the
  74. // user.
  75. constexpr base::TimeDelta kEffectiveResolutionRepeatingDelay =
  76. base::Minutes(30);
  77. display::DisplayManager* GetDisplayManager() {
  78. return Shell::Get()->display_manager();
  79. }
  80. void SetDisplayPropertiesOnHost(AshWindowTreeHost* ash_host,
  81. const display::Display& display) {
  82. const display::Display::Rotation effective_rotation =
  83. display.panel_rotation();
  84. aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
  85. ash_host->UpdateCursorConfig();
  86. ash_host->SetRootWindowTransformer(
  87. CreateRootWindowTransformerForDisplay(display));
  88. host->SetDisplayTransformHint(
  89. display::DisplayRotationToOverlayTransform(effective_rotation));
  90. const display::ManagedDisplayInfo& display_info =
  91. GetDisplayManager()->GetDisplayInfo(display.id());
  92. if (display::features::IsRoundedDisplayEnabled()) {
  93. // Set/Update rounded corners on the display.
  94. ui::Layer* root_layer = host->window()->layer();
  95. DCHECK(root_layer);
  96. root_layer->SetRoundedCornerRadius(display_info.rounded_corners_radii());
  97. // If root_layer does not have rounded corners, setting the fast rounded
  98. // corner optimization on does not have any effect.
  99. root_layer->SetIsFastRoundedCorner(
  100. !display_info.rounded_corners_radii().IsEmpty());
  101. }
  102. // Just moving the display requires the full redraw.
  103. // chrome-os-partner:33558.
  104. host->compositor()->ScheduleFullRedraw();
  105. }
  106. void ClearDisplayPropertiesOnHost(AshWindowTreeHost* ash_host) {
  107. ash_host->ClearCursorConfig();
  108. }
  109. aura::Window* GetWindow(AshWindowTreeHost* ash_host) {
  110. CHECK(ash_host->AsWindowTreeHost());
  111. return ash_host->AsWindowTreeHost()->window();
  112. }
  113. // Returns the index to the enum - |EffectiveResolution|. The enum value
  114. // represents the resolution that exactly matches the primary display's
  115. // effective resolution.
  116. int GetEffectiveResolutionUMAIndex(const display::Display& display) {
  117. const gfx::Size effective_size = display.size();
  118. // The UMA enum index for portrait mode has 1 subtracted from itself. This
  119. // differentiates it from the landscape mode.
  120. return effective_size.width() > effective_size.height()
  121. ? effective_size.width() * effective_size.height()
  122. : effective_size.width() * effective_size.height() - 1;
  123. }
  124. void RepeatingEffectiveResolutionUMA(base::RepeatingTimer* timer,
  125. bool is_first_run) {
  126. display::Display internal_display;
  127. const auto* session_controller = Shell::Get()->session_controller();
  128. // Record the UMA only when this is an active user session and the
  129. // internal display is present.
  130. if (display::HasInternalDisplay() &&
  131. display::Screen::GetScreen()->GetDisplayWithDisplayId(
  132. display::Display::InternalDisplayId(), &internal_display) &&
  133. session_controller->IsActiveUserSessionStarted() &&
  134. session_controller->GetSessionState() ==
  135. session_manager::SessionState::ACTIVE) {
  136. base::UmaHistogramSparse(
  137. "Ash.Display.InternalDisplay.ActiveEffectiveResolution",
  138. GetEffectiveResolutionUMAIndex(internal_display));
  139. }
  140. // The first run of the repeating timer is half the actual delay. Reset the
  141. // timer after the first run with the correct delay.
  142. if (is_first_run && timer) {
  143. timer->Start(
  144. FROM_HERE, kEffectiveResolutionRepeatingDelay,
  145. base::BindRepeating(&RepeatingEffectiveResolutionUMA,
  146. nullptr /*timer=*/, false /*is_first_run=*/));
  147. }
  148. }
  149. } // namespace
  150. // A utility class to store/restore focused/active window
  151. // when the display configuration has changed.
  152. class FocusActivationStore {
  153. public:
  154. FocusActivationStore()
  155. : activation_client_(nullptr),
  156. capture_client_(nullptr),
  157. focus_client_(nullptr),
  158. focused_(nullptr),
  159. active_(nullptr) {}
  160. FocusActivationStore(const FocusActivationStore&) = delete;
  161. FocusActivationStore& operator=(const FocusActivationStore&) = delete;
  162. void Store(bool clear_focus) {
  163. if (!activation_client_) {
  164. aura::Window* root = Shell::GetPrimaryRootWindow();
  165. activation_client_ = ::wm::GetActivationClient(root);
  166. capture_client_ = aura::client::GetCaptureClient(root);
  167. focus_client_ = aura::client::GetFocusClient(root);
  168. }
  169. focused_ = focus_client_->GetFocusedWindow();
  170. if (focused_)
  171. tracker_.Add(focused_);
  172. active_ = activation_client_->GetActiveWindow();
  173. if (active_ && focused_ != active_)
  174. tracker_.Add(active_);
  175. // Deactivate the window to close menu / bubble windows. Deactivating by
  176. // setting active window to nullptr to avoid side effects of activating an
  177. // arbitrary window, such as covering |active_| before Restore().
  178. if (clear_focus && active_)
  179. activation_client_->ActivateWindow(nullptr);
  180. // Release capture if any.
  181. capture_client_->SetCapture(nullptr);
  182. // Clear the focused window if any. This is necessary because a
  183. // window may be deleted when losing focus (fullscreen flash for
  184. // example). If the focused window is still alive after move, it'll
  185. // be re-focused below.
  186. if (clear_focus)
  187. focus_client_->FocusWindow(nullptr);
  188. }
  189. void Restore() {
  190. // Restore focused or active window if it's still alive.
  191. if (focused_ && tracker_.Contains(focused_)) {
  192. focus_client_->FocusWindow(focused_);
  193. } else if (active_ && tracker_.Contains(active_)) {
  194. activation_client_->ActivateWindow(active_);
  195. }
  196. if (focused_)
  197. tracker_.Remove(focused_);
  198. if (active_)
  199. tracker_.Remove(active_);
  200. focused_ = nullptr;
  201. active_ = nullptr;
  202. }
  203. private:
  204. ::wm::ActivationClient* activation_client_;
  205. aura::client::CaptureClient* capture_client_;
  206. aura::client::FocusClient* focus_client_;
  207. aura::WindowTracker tracker_;
  208. aura::Window* focused_;
  209. aura::Window* active_;
  210. };
  211. ////////////////////////////////////////////////////////////////////////////////
  212. // WindowTreeHostManager
  213. WindowTreeHostManager::WindowTreeHostManager()
  214. : primary_tree_host_for_replace_(nullptr),
  215. focus_activation_store_(new FocusActivationStore()),
  216. cursor_window_controller_(new CursorWindowController()),
  217. mirror_window_controller_(new MirrorWindowController()),
  218. cursor_display_id_for_restore_(display::kInvalidDisplayId) {
  219. // Reset primary display to make sure that tests don't use
  220. // stale display info from previous tests.
  221. primary_display_id = display::kInvalidDisplayId;
  222. }
  223. WindowTreeHostManager::~WindowTreeHostManager() = default;
  224. void WindowTreeHostManager::Start() {
  225. display_observer_.emplace(this);
  226. Shell::Get()
  227. ->display_configurator()
  228. ->content_protection_manager()
  229. ->AddObserver(this);
  230. Shell::Get()->display_manager()->set_delegate(this);
  231. // Start a repeating timer to send UMA at fixed intervals. The first run is at
  232. // half the delay time.
  233. effective_resolution_UMA_timer_ = std::make_unique<base::RepeatingTimer>();
  234. effective_resolution_UMA_timer_->Start(
  235. FROM_HERE, kEffectiveResolutionRepeatingDelay / 2,
  236. base::BindRepeating(&RepeatingEffectiveResolutionUMA,
  237. effective_resolution_UMA_timer_.get(),
  238. true /*is_first_run=*/));
  239. }
  240. void WindowTreeHostManager::Shutdown() {
  241. for (auto& observer : observers_)
  242. observer.OnWindowTreeHostManagerShutdown();
  243. effective_resolution_UMA_timer_->Reset();
  244. // Unset the display manager's delegate here because
  245. // DisplayManager outlives WindowTreeHostManager.
  246. Shell::Get()->display_manager()->set_delegate(nullptr);
  247. cursor_window_controller_.reset();
  248. mirror_window_controller_.reset();
  249. Shell::Get()
  250. ->display_configurator()
  251. ->content_protection_manager()
  252. ->RemoveObserver(this);
  253. display_observer_.reset();
  254. int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
  255. // Delete non primary root window controllers first, then
  256. // delete the primary root window controller.
  257. aura::Window::Windows root_windows =
  258. WindowTreeHostManager::GetAllRootWindows();
  259. std::vector<RootWindowController*> to_delete;
  260. RootWindowController* primary_rwc = nullptr;
  261. for (aura::Window::Windows::iterator iter = root_windows.begin();
  262. iter != root_windows.end(); ++iter) {
  263. RootWindowController* rwc = RootWindowController::ForWindow(*iter);
  264. if (GetRootWindowSettings(*iter)->display_id == primary_id)
  265. primary_rwc = rwc;
  266. else
  267. to_delete.push_back(rwc);
  268. }
  269. CHECK(primary_rwc);
  270. Shell::SetRootWindowForNewWindows(nullptr);
  271. for (auto* rwc : to_delete)
  272. delete rwc;
  273. delete primary_rwc;
  274. }
  275. void WindowTreeHostManager::CreatePrimaryHost(
  276. const AshWindowTreeHostInitParams& init_params) {
  277. const display::Display& primary_candidate =
  278. GetDisplayManager()->GetPrimaryDisplayCandidate();
  279. primary_display_id = primary_candidate.id();
  280. CHECK_NE(display::kInvalidDisplayId, primary_display_id);
  281. AddWindowTreeHostForDisplay(primary_candidate, init_params);
  282. }
  283. void WindowTreeHostManager::InitHosts() {
  284. RootWindowController::CreateForPrimaryDisplay(
  285. window_tree_hosts_[primary_display_id]);
  286. display::DisplayManager* display_manager = GetDisplayManager();
  287. for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
  288. const display::Display& display = display_manager->GetDisplayAt(i);
  289. if (primary_display_id != display.id()) {
  290. AshWindowTreeHost* ash_host =
  291. AddWindowTreeHostForDisplay(display, AshWindowTreeHostInitParams());
  292. RootWindowController::CreateForSecondaryDisplay(ash_host);
  293. }
  294. }
  295. // Record display zoom for the primary display for https://crbug.com/955071.
  296. // This can be removed after M79.
  297. const display::ManagedDisplayInfo& display_info =
  298. display_manager->GetDisplayInfo(primary_display_id);
  299. int zoom_percent = std::round(display_info.zoom_factor() * 100);
  300. constexpr int kMaxValue = 300;
  301. constexpr int kBucketSize = 5;
  302. constexpr int kBucketCount = kMaxValue / kBucketSize + 1;
  303. base::LinearHistogram::FactoryGet(
  304. "Ash.Display.PrimaryDisplayZoomAtStartup", kBucketSize, kMaxValue,
  305. kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag)
  306. ->Add(zoom_percent);
  307. for (auto& observer : observers_)
  308. observer.OnDisplaysInitialized();
  309. }
  310. void WindowTreeHostManager::AddObserver(Observer* observer) {
  311. observers_.AddObserver(observer);
  312. }
  313. void WindowTreeHostManager::RemoveObserver(Observer* observer) {
  314. observers_.RemoveObserver(observer);
  315. }
  316. // static
  317. int64_t WindowTreeHostManager::GetPrimaryDisplayId() {
  318. CHECK_NE(display::kInvalidDisplayId, primary_display_id);
  319. return primary_display_id;
  320. }
  321. // static
  322. bool WindowTreeHostManager::HasValidPrimaryDisplayId() {
  323. return primary_display_id != display::kInvalidDisplayId;
  324. }
  325. aura::Window* WindowTreeHostManager::GetPrimaryRootWindow() {
  326. // If |primary_tree_host_for_replace_| is set, it means |primary_display_id|
  327. // is kInvalidDisplayId.
  328. if (primary_tree_host_for_replace_)
  329. return GetWindow(primary_tree_host_for_replace_);
  330. return GetRootWindowForDisplayId(primary_display_id);
  331. }
  332. aura::Window* WindowTreeHostManager::GetRootWindowForDisplayId(int64_t id) {
  333. AshWindowTreeHost* host = GetAshWindowTreeHostForDisplayId(id);
  334. return host ? GetWindow(host) : nullptr;
  335. }
  336. AshWindowTreeHost* WindowTreeHostManager::GetAshWindowTreeHostForDisplayId(
  337. int64_t display_id) {
  338. const auto host = window_tree_hosts_.find(display_id);
  339. if (host != window_tree_hosts_.end())
  340. return host->second;
  341. return mirror_window_controller_->GetAshWindowTreeHostForDisplayId(
  342. display_id);
  343. }
  344. aura::Window::Windows WindowTreeHostManager::GetAllRootWindows() {
  345. aura::Window::Windows windows;
  346. for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
  347. it != window_tree_hosts_.end(); ++it) {
  348. DCHECK(it->second);
  349. if (RootWindowController::ForWindow(GetWindow(it->second)))
  350. windows.push_back(GetWindow(it->second));
  351. }
  352. return windows;
  353. }
  354. gfx::Insets WindowTreeHostManager::GetOverscanInsets(int64_t display_id) const {
  355. return GetDisplayManager()->GetOverscanInsets(display_id);
  356. }
  357. void WindowTreeHostManager::SetOverscanInsets(
  358. int64_t display_id,
  359. const gfx::Insets& insets_in_dip) {
  360. GetDisplayManager()->SetOverscanInsets(display_id, insets_in_dip);
  361. }
  362. std::vector<RootWindowController*>
  363. WindowTreeHostManager::GetAllRootWindowControllers() {
  364. std::vector<RootWindowController*> controllers;
  365. for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin();
  366. it != window_tree_hosts_.end(); ++it) {
  367. RootWindowController* controller =
  368. RootWindowController::ForWindow(GetWindow(it->second));
  369. if (controller)
  370. controllers.push_back(controller);
  371. }
  372. return controllers;
  373. }
  374. void WindowTreeHostManager::UpdateMouseLocationAfterDisplayChange() {
  375. // If the mouse is currently on a display in native location,
  376. // use the same native location. Otherwise find the display closest
  377. // to the current cursor location in screen coordinates.
  378. gfx::Point point_in_screen =
  379. display::Screen::GetScreen()->GetCursorScreenPoint();
  380. gfx::Point target_location_in_native;
  381. int64_t closest_distance_squared = -1;
  382. display::DisplayManager* display_manager = GetDisplayManager();
  383. aura::Window* dst_root_window = nullptr;
  384. for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
  385. const display::Display& display = display_manager->GetDisplayAt(i);
  386. const display::ManagedDisplayInfo display_info =
  387. display_manager->GetDisplayInfo(display.id());
  388. aura::Window* root_window = GetRootWindowForDisplayId(display.id());
  389. if (display_info.bounds_in_native().Contains(
  390. cursor_location_in_native_coords_for_restore_)) {
  391. dst_root_window = root_window;
  392. target_location_in_native = cursor_location_in_native_coords_for_restore_;
  393. break;
  394. }
  395. gfx::Point center = display.bounds().CenterPoint();
  396. // Use the distance squared from the center of the dislay. This is not
  397. // exactly "closest" display, but good enough to pick one
  398. // appropriate (and there are at most two displays).
  399. // We don't care about actual distance, only relative to other displays, so
  400. // using the LengthSquared() is cheaper than Length().
  401. int64_t distance_squared = (center - point_in_screen).LengthSquared();
  402. if (closest_distance_squared < 0 ||
  403. closest_distance_squared > distance_squared) {
  404. aura::Window* root_window = GetRootWindowForDisplayId(display.id());
  405. ::wm::ConvertPointFromScreen(root_window, &center);
  406. root_window->GetHost()->ConvertDIPToScreenInPixels(&center);
  407. dst_root_window = root_window;
  408. target_location_in_native = center;
  409. closest_distance_squared = distance_squared;
  410. }
  411. }
  412. gfx::Point target_location_in_root = target_location_in_native;
  413. dst_root_window->GetHost()->ConvertScreenInPixelsToDIP(
  414. &target_location_in_root);
  415. gfx::Point target_location_in_screen = target_location_in_root;
  416. ::wm::ConvertPointToScreen(dst_root_window, &target_location_in_screen);
  417. const display::Display& target_display =
  418. display_manager->FindDisplayContainingPoint(target_location_in_screen);
  419. // If the original location isn't on any of new display, let ozone move
  420. // the cursor.
  421. if (!target_display.is_valid())
  422. return;
  423. int64_t target_display_id = target_display.id();
  424. // Do not move the cursor if the cursor's location did not change. This avoids
  425. // moving (and showing) the cursor:
  426. // - At startup.
  427. // - When the device is rotated in tablet mode.
  428. // |cursor_display_id_for_restore_| is checked to ensure that the cursor is
  429. // moved when the cursor's native position does not change but the display
  430. // that it is on has changed. This occurs when swapping the primary display.
  431. if (target_location_in_native !=
  432. cursor_location_in_native_coords_for_restore_ ||
  433. target_display_id != cursor_display_id_for_restore_) {
  434. if (Shell::Get()->cursor_manager()) {
  435. if (Shell::Get()->cursor_manager()->IsCursorVisible()) {
  436. dst_root_window->MoveCursorTo(target_location_in_root);
  437. } else if (target_display_id != cursor_display_id_for_restore_) {
  438. Shell::Get()->cursor_manager()->SetDisplay(target_display);
  439. }
  440. }
  441. } else if (target_location_in_screen !=
  442. cursor_location_in_screen_coords_for_restore_) {
  443. // The cursor's native position did not change but its screen position did
  444. // change. This occurs when the scale factor or the rotation of the display
  445. // that the cursor is on changes.
  446. // TODO: conditional should not be necessary. http://crbug.com/631103.
  447. if (Shell::Get()->cursor_manager())
  448. Shell::Get()->cursor_manager()->SetDisplay(target_display);
  449. // Update the cursor's root location. This ends up dispatching a synthetic
  450. // mouse move. The synthetic mouse move updates the composited cursor's
  451. // location and hover effects. Synthetic mouse moves do not affect the
  452. // cursor's visibility.
  453. dst_root_window->GetHost()->dispatcher()->OnCursorMovedToRootLocation(
  454. target_location_in_root);
  455. }
  456. }
  457. bool WindowTreeHostManager::UpdateWorkAreaOfDisplayNearestWindow(
  458. const aura::Window* window,
  459. const gfx::Insets& insets) {
  460. const aura::Window* root_window = window->GetRootWindow();
  461. int64_t id = GetRootWindowSettings(root_window)->display_id;
  462. // if id is |kInvaildDisplayID|, it's being deleted.
  463. DCHECK(id != display::kInvalidDisplayId);
  464. return GetDisplayManager()->UpdateWorkAreaOfDisplay(id, insets);
  465. }
  466. void WindowTreeHostManager::OnDisplayAdded(const display::Display& display) {
  467. // If we're switching from/to offscreen WTH, we need to
  468. // create new WTH for primary display instead of reusing.
  469. if (primary_tree_host_for_replace_ &&
  470. (GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_))
  471. ->display_id == display::kUnifiedDisplayId ||
  472. display.id() == display::kUnifiedDisplayId)) {
  473. DCHECK_EQ(display::kInvalidDisplayId, primary_display_id);
  474. primary_display_id = display.id();
  475. AshWindowTreeHost* ash_host =
  476. AddWindowTreeHostForDisplay(display, AshWindowTreeHostInitParams());
  477. RootWindowController* new_root_window_controller =
  478. RootWindowController::CreateForSecondaryDisplay(ash_host);
  479. // Magnifier controllers keep pointers to the current root window.
  480. // Update them here to avoid accessing them later.
  481. Shell::Get()->fullscreen_magnifier_controller()->SwitchTargetRootWindow(
  482. ash_host->AsWindowTreeHost()->window(), false);
  483. Shell::Get()
  484. ->partial_magnifier_controller()
  485. ->SwitchTargetRootWindowIfNeeded(
  486. ash_host->AsWindowTreeHost()->window());
  487. AshWindowTreeHost* to_delete = primary_tree_host_for_replace_;
  488. // Show the shelf if the original WTH had a visible system
  489. // tray. It may or may not be visible depending on OOBE state.
  490. RootWindowController* old_root_window_controller =
  491. RootWindowController::ForWindow(
  492. to_delete->AsWindowTreeHost()->window());
  493. TrayBackgroundView* old_tray =
  494. old_root_window_controller->GetStatusAreaWidget()
  495. ->unified_system_tray();
  496. TrayBackgroundView* new_tray =
  497. new_root_window_controller->GetStatusAreaWidget()
  498. ->unified_system_tray();
  499. if (old_tray->GetWidget()->IsVisible()) {
  500. new_tray->SetVisiblePreferred(true);
  501. new_tray->GetWidget()->Show();
  502. }
  503. // |to_delete| has already been removed from |window_tree_hosts_|.
  504. DCHECK(std::none_of(
  505. window_tree_hosts_.cbegin(), window_tree_hosts_.cend(),
  506. [to_delete](const std::pair<int64_t, AshWindowTreeHost*>& pair) {
  507. return pair.second == to_delete;
  508. }));
  509. DeleteHost(to_delete);
  510. DCHECK(!primary_tree_host_for_replace_);
  511. } else if (primary_tree_host_for_replace_) {
  512. // TODO(oshima): It should be possible to consolidate logic for
  513. // unified and non unified, but I'm keeping them separated to minimize
  514. // the risk in M44. I'll consolidate this in M45.
  515. DCHECK(window_tree_hosts_.empty());
  516. AshWindowTreeHost* ash_host = primary_tree_host_for_replace_;
  517. primary_tree_host_for_replace_ = nullptr;
  518. primary_display_id = display.id();
  519. window_tree_hosts_[display.id()] = ash_host;
  520. GetRootWindowSettings(GetWindow(ash_host))->display_id = display.id();
  521. const display::ManagedDisplayInfo& display_info =
  522. GetDisplayManager()->GetDisplayInfo(display.id());
  523. ash_host->AsWindowTreeHost()->SetBoundsInPixels(
  524. display_info.bounds_in_native());
  525. SetDisplayPropertiesOnHost(ash_host, display);
  526. } else {
  527. if (primary_display_id == display::kInvalidDisplayId)
  528. primary_display_id = display.id();
  529. DCHECK(!window_tree_hosts_.empty());
  530. AshWindowTreeHost* ash_host =
  531. AddWindowTreeHostForDisplay(display, AshWindowTreeHostInitParams());
  532. RootWindowController::CreateForSecondaryDisplay(ash_host);
  533. }
  534. }
  535. void WindowTreeHostManager::DeleteHost(AshWindowTreeHost* host_to_delete) {
  536. ClearDisplayPropertiesOnHost(host_to_delete);
  537. aura::Window* root_being_deleted = GetWindow(host_to_delete);
  538. RootWindowController* controller =
  539. RootWindowController::ForWindow(root_being_deleted);
  540. DCHECK(controller);
  541. // Some code relies on this being called before MoveWindowsTo().
  542. Shell::Get()->OnRootWindowWillShutdown(root_being_deleted);
  543. aura::Window* primary_root_after_host_deletion =
  544. GetRootWindowForDisplayId(GetPrimaryDisplayId());
  545. controller->MoveWindowsTo(primary_root_after_host_deletion);
  546. // Delete most of root window related objects, but don't delete
  547. // root window itself yet because the stack may be using it.
  548. controller->Shutdown();
  549. if (primary_tree_host_for_replace_ == host_to_delete)
  550. primary_tree_host_for_replace_ = nullptr;
  551. DCHECK_EQ(primary_root_after_host_deletion, Shell::GetPrimaryRootWindow());
  552. if (Shell::GetRootWindowForNewWindows() == root_being_deleted) {
  553. Shell::SetRootWindowForNewWindows(primary_root_after_host_deletion);
  554. }
  555. // NOTE: ShelfWidget is gone, but Shelf still exists until this task runs.
  556. base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, controller);
  557. }
  558. void WindowTreeHostManager::OnDisplayRemoved(const display::Display& display) {
  559. AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()];
  560. CHECK(host_to_delete) << display.ToString();
  561. // When the primary root window's display is removed, move the primary
  562. // root to the other display.
  563. if (primary_display_id == display.id()) {
  564. // Temporarily store the primary root window in
  565. // |primary_root_window_for_replace_| when replacing the display.
  566. if (window_tree_hosts_.size() == 1) {
  567. primary_display_id = display::kInvalidDisplayId;
  568. primary_tree_host_for_replace_ = host_to_delete;
  569. // Display for root window will be deleted when the Primary RootWindow
  570. // is deleted by the Shell.
  571. window_tree_hosts_.erase(display.id());
  572. return;
  573. }
  574. for (const auto& pair : window_tree_hosts_) {
  575. if (pair.first != display.id()) {
  576. primary_display_id = pair.first;
  577. break;
  578. }
  579. }
  580. CHECK_NE(display::kInvalidDisplayId, primary_display_id);
  581. AshWindowTreeHost* primary_host = host_to_delete;
  582. // Delete the other host instead.
  583. host_to_delete = window_tree_hosts_[primary_display_id];
  584. GetRootWindowSettings(GetWindow(host_to_delete))->display_id = display.id();
  585. // Setup primary root.
  586. window_tree_hosts_[primary_display_id] = primary_host;
  587. GetRootWindowSettings(GetWindow(primary_host))->display_id =
  588. primary_display_id;
  589. OnDisplayMetricsChanged(
  590. GetDisplayManager()->GetDisplayForId(primary_display_id),
  591. DISPLAY_METRIC_BOUNDS);
  592. }
  593. DeleteHost(host_to_delete);
  594. // The window tree host should be erased at last because some handlers can
  595. // access to the host through GetRootWindowForDisplayId() during
  596. // MoveWindowsTo(). See http://crbug.com/415222
  597. window_tree_hosts_.erase(display.id());
  598. }
  599. void WindowTreeHostManager::OnDisplayMetricsChanged(
  600. const display::Display& display,
  601. uint32_t metrics) {
  602. if (!(metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION |
  603. DISPLAY_METRIC_DEVICE_SCALE_FACTOR))) {
  604. return;
  605. }
  606. const display::ManagedDisplayInfo& display_info =
  607. GetDisplayManager()->GetDisplayInfo(display.id());
  608. DCHECK(!display_info.bounds_in_native().IsEmpty());
  609. AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()];
  610. ash_host->AsWindowTreeHost()->SetBoundsInPixels(
  611. display_info.bounds_in_native());
  612. SetDisplayPropertiesOnHost(ash_host, display);
  613. }
  614. void WindowTreeHostManager::OnHostResized(aura::WindowTreeHost* host) {
  615. display::Display display =
  616. display::Screen::GetScreen()->GetDisplayNearestWindow(host->window());
  617. display::DisplayManager* display_manager = GetDisplayManager();
  618. if (display_manager->UpdateDisplayBounds(display.id(),
  619. host->GetBoundsInPixels())) {
  620. mirror_window_controller_->UpdateWindow();
  621. cursor_window_controller_->UpdateContainer();
  622. }
  623. }
  624. void WindowTreeHostManager::OnDisplaySecurityChanged(int64_t display_id,
  625. bool secure) {
  626. AshWindowTreeHost* host = GetAshWindowTreeHostForDisplayId(display_id);
  627. // No host for internal display in docked mode.
  628. if (!host)
  629. return;
  630. ui::Compositor* compositor = host->AsWindowTreeHost()->compositor();
  631. compositor->SetOutputIsSecure(secure);
  632. compositor->ScheduleFullRedraw();
  633. }
  634. void WindowTreeHostManager::CreateOrUpdateMirroringDisplay(
  635. const display::DisplayInfoList& info_list) {
  636. if (GetDisplayManager()->IsInMirrorMode() ||
  637. GetDisplayManager()->IsInUnifiedMode()) {
  638. mirror_window_controller_->UpdateWindow(info_list);
  639. cursor_window_controller_->UpdateContainer();
  640. } else {
  641. NOTREACHED();
  642. }
  643. }
  644. void WindowTreeHostManager::CloseMirroringDisplayIfNotNecessary() {
  645. mirror_window_controller_->CloseIfNotNecessary();
  646. // If cursor_compositing is enabled for large cursor, the cursor window is
  647. // always on the desktop display (the visible cursor on the non-desktop
  648. // display is drawn through compositor mirroring). Therefore, it's unnecessary
  649. // to handle the cursor_window at all. See: http://crbug.com/412910
  650. if (!cursor_window_controller_->is_cursor_compositing_enabled())
  651. cursor_window_controller_->UpdateContainer();
  652. }
  653. void WindowTreeHostManager::PreDisplayConfigurationChange(bool clear_focus) {
  654. for (auto& observer : observers_)
  655. observer.OnDisplayConfigurationChanging();
  656. focus_activation_store_->Store(clear_focus);
  657. display::Screen* screen = display::Screen::GetScreen();
  658. gfx::Point point_in_screen = screen->GetCursorScreenPoint();
  659. cursor_location_in_screen_coords_for_restore_ = point_in_screen;
  660. display::Display display = screen->GetDisplayNearestPoint(point_in_screen);
  661. cursor_display_id_for_restore_ = display.id();
  662. gfx::Point point_in_native = point_in_screen;
  663. aura::Window* root_window = GetRootWindowForDisplayId(display.id());
  664. ::wm::ConvertPointFromScreen(root_window, &point_in_native);
  665. root_window->GetHost()->ConvertDIPToScreenInPixels(&point_in_native);
  666. cursor_location_in_native_coords_for_restore_ = point_in_native;
  667. }
  668. void WindowTreeHostManager::SetPrimaryDisplayId(int64_t id) {
  669. // TODO(oshima): Move primary display management to DisplayManager.
  670. DCHECK_NE(display::kInvalidDisplayId, id);
  671. if (id == display::kInvalidDisplayId || primary_display_id == id ||
  672. window_tree_hosts_.size() < 2) {
  673. return;
  674. }
  675. const display::Display& new_primary_display =
  676. GetDisplayManager()->GetDisplayForId(id);
  677. if (!new_primary_display.is_valid()) {
  678. LOG(ERROR) << "Invalid or non-existent display is requested:"
  679. << new_primary_display.ToString();
  680. return;
  681. }
  682. display::DisplayManager* display_manager = GetDisplayManager();
  683. DCHECK(new_primary_display.is_valid());
  684. DCHECK(display_manager->GetDisplayForId(new_primary_display.id()).is_valid());
  685. AshWindowTreeHost* non_primary_host =
  686. window_tree_hosts_[new_primary_display.id()];
  687. LOG_IF(ERROR, !non_primary_host)
  688. << "Unknown display is requested in SetPrimaryDisplay: id="
  689. << new_primary_display.id();
  690. if (!non_primary_host)
  691. return;
  692. display::Display old_primary_display =
  693. display::Screen::GetScreen()->GetPrimaryDisplay();
  694. DCHECK_EQ(old_primary_display.id(), primary_display_id);
  695. // Swap root windows between current and new primary display.
  696. AshWindowTreeHost* primary_host = window_tree_hosts_[primary_display_id];
  697. CHECK(primary_host);
  698. CHECK_NE(primary_host, non_primary_host);
  699. aura::Window* primary_window = GetWindow(primary_host);
  700. aura::Window* non_primary_window = GetWindow(non_primary_host);
  701. window_tree_hosts_[new_primary_display.id()] = primary_host;
  702. GetRootWindowSettings(primary_window)->display_id = new_primary_display.id();
  703. window_tree_hosts_[old_primary_display.id()] = non_primary_host;
  704. GetRootWindowSettings(non_primary_window)->display_id =
  705. old_primary_display.id();
  706. // Ensure that color spaces for the root windows reflect those of their new
  707. // displays. If these go out of sync, we can lose the ability to composite HDR
  708. // content.
  709. primary_host->AsWindowTreeHost()->compositor()->SetDisplayColorSpaces(
  710. new_primary_display.color_spaces());
  711. non_primary_host->AsWindowTreeHost()->compositor()->SetDisplayColorSpaces(
  712. old_primary_display.color_spaces());
  713. std::u16string old_primary_title = primary_window->GetTitle();
  714. primary_window->SetTitle(non_primary_window->GetTitle());
  715. non_primary_window->SetTitle(old_primary_title);
  716. const display::DisplayLayout& layout =
  717. GetDisplayManager()->GetCurrentDisplayLayout();
  718. // The requested primary id can be same as one in the stored layout
  719. // when the primary id is set after new displays are connected.
  720. // Only update the layout if it is requested to swap primary display.
  721. if (layout.primary_id != new_primary_display.id()) {
  722. std::unique_ptr<display::DisplayLayout> swapped_layout = layout.Copy();
  723. swapped_layout->SwapPrimaryDisplay(new_primary_display.id());
  724. display::DisplayIdList list = display_manager->GetConnectedDisplayIdList();
  725. GetDisplayManager()->layout_store()->RegisterLayoutForDisplayIdList(
  726. list, std::move(swapped_layout));
  727. }
  728. primary_display_id = new_primary_display.id();
  729. UpdateWorkAreaOfDisplayNearestWindow(GetWindow(primary_host),
  730. old_primary_display.GetWorkAreaInsets());
  731. UpdateWorkAreaOfDisplayNearestWindow(GetWindow(non_primary_host),
  732. new_primary_display.GetWorkAreaInsets());
  733. // Update the dispay manager with new display info.
  734. GetDisplayManager()->set_force_bounds_changed(true);
  735. GetDisplayManager()->UpdateDisplays();
  736. GetDisplayManager()->set_force_bounds_changed(false);
  737. }
  738. void WindowTreeHostManager::PostDisplayConfigurationChange() {
  739. focus_activation_store_->Restore();
  740. for (auto& observer : observers_)
  741. observer.OnDisplayConfigurationChanged();
  742. UpdateMouseLocationAfterDisplayChange();
  743. // Enable cursor compositing, so that cursor could be mirrored to destination
  744. // displays along with other display content.
  745. Shell::Get()->UpdateCursorCompositingEnabled();
  746. }
  747. ui::EventDispatchDetails WindowTreeHostManager::DispatchKeyEventPostIME(
  748. ui::KeyEvent* event) {
  749. aura::Window* root_window = nullptr;
  750. if (event->target()) {
  751. root_window = static_cast<aura::Window*>(event->target())->GetRootWindow();
  752. DCHECK(root_window);
  753. } else {
  754. // Getting the active root window to dispatch the event. This isn't
  755. // significant as the event will be sent to the window resolved by
  756. // aura::client::FocusClient which is FocusController in ash.
  757. aura::Window* active_window = window_util::GetActiveWindow();
  758. root_window = active_window ? active_window->GetRootWindow()
  759. : Shell::GetPrimaryRootWindow();
  760. }
  761. return root_window->GetHost()->DispatchKeyEventPostIME(event);
  762. }
  763. const display::Display* WindowTreeHostManager::GetDisplayById(
  764. int64_t display_id) const {
  765. const display::Display& display =
  766. GetDisplayManager()->GetDisplayForId(display_id);
  767. return display.is_valid() ? &display : nullptr;
  768. }
  769. void WindowTreeHostManager::SetCurrentEventTargeterSourceHost(
  770. aura::WindowTreeHost* targeter_src_host) {
  771. NOTIMPLEMENTED();
  772. }
  773. AshWindowTreeHost* WindowTreeHostManager::AddWindowTreeHostForDisplay(
  774. const display::Display& display,
  775. const AshWindowTreeHostInitParams& init_params) {
  776. static int host_count = 0;
  777. const display::ManagedDisplayInfo& display_info =
  778. GetDisplayManager()->GetDisplayInfo(display.id());
  779. AshWindowTreeHostInitParams params_with_bounds(init_params);
  780. params_with_bounds.initial_bounds = display_info.bounds_in_native();
  781. if (display.id() == display::kUnifiedDisplayId) {
  782. params_with_bounds.offscreen = true;
  783. params_with_bounds.delegate = mirror_window_controller();
  784. } else {
  785. params_with_bounds.delegate = this;
  786. }
  787. params_with_bounds.display_id = display.id();
  788. params_with_bounds.device_scale_factor = display.device_scale_factor();
  789. // TODO(crbug/1261776): Temporarily increase compositor memory limit for
  790. // 4K+ displays to avoid rendering corruption.
  791. // Check both width and height in case of rotated display.
  792. if (std::max(display.GetSizeInPixel().width(),
  793. display.GetSizeInPixel().height()) >
  794. kUICompositorMemoryLimitDisplaySizeThreshold) {
  795. params_with_bounds.compositor_memory_limit_mb =
  796. kUICompositorLargeMemoryLimitMB;
  797. }
  798. // The AshWindowTreeHost ends up owned by the RootWindowControllers created
  799. // by this class.
  800. AshWindowTreeHost* ash_host =
  801. AshWindowTreeHost::Create(params_with_bounds).release();
  802. aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
  803. Shell::Get()->frame_throttling_controller()->OnWindowTreeHostCreated(host);
  804. DCHECK(!host->has_input_method());
  805. if (!input_method_) { // Singleton input method instance for Ash.
  806. input_method_ = ui::CreateInputMethod(this, host->GetAcceleratedWidget());
  807. // Makes sure the input method is focused by default when created, because
  808. // Ash uses singleton InputMethod and it won't call OnFocus/OnBlur when
  809. // the active window changed.
  810. input_method_->OnFocus();
  811. }
  812. host->SetSharedInputMethod(input_method_.get());
  813. host->window()->SetName(base::StringPrintf(
  814. "%sRootWindow-%d", params_with_bounds.offscreen ? "Offscreen" : "",
  815. host_count++));
  816. host->window()->SetTitle(base::UTF8ToUTF16(display_info.name()));
  817. host->compositor()->SetBackgroundColor(SK_ColorBLACK);
  818. // No need to remove our observer observer because the WindowTreeHostManager
  819. // outlives the host.
  820. host->AddObserver(this);
  821. InitRootWindowSettings(host->window())->display_id = display.id();
  822. host->InitHost();
  823. host->window()->Show();
  824. window_tree_hosts_[display.id()] = ash_host;
  825. SetDisplayPropertiesOnHost(ash_host, display);
  826. ash_host->ConfineCursorToRootWindow();
  827. return ash_host;
  828. }
  829. } // namespace ash