display_configuration_controller.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2016 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/display_configuration_controller.h"
  5. #include <memory>
  6. #include "ash/display/display_animator.h"
  7. #include "ash/display/display_util.h"
  8. #include "ash/display/window_tree_host_manager.h"
  9. #include "ash/public/cpp/shelf_types.h"
  10. #include "ash/root_window_controller.h"
  11. #include "ash/rotator/screen_rotation_animator.h"
  12. #include "ash/shelf/shelf.h"
  13. #include "ash/shell.h"
  14. #include "ash/strings/grit/ash_strings.h"
  15. #include "ash/wallpaper/wallpaper_controller_impl.h"
  16. #include "base/bind.h"
  17. #include "base/time/time.h"
  18. #include "chromeos/system/devicemode.h"
  19. #include "ui/base/l10n/l10n_util.h"
  20. #include "ui/display/display_layout.h"
  21. #include "ui/display/manager/display_manager.h"
  22. namespace ash {
  23. namespace {
  24. // Specifies how long the display change should have been disabled
  25. // after each display change operations.
  26. // |kCycleDisplayThrottleTimeoutMs| is set to be longer to avoid
  27. // changing the settings while the system is still configurating
  28. // displays. It will be overriden by |kAfterDisplayChangeThrottleTimeoutMs|
  29. // when the display change happens, so the actual timeout is much shorter.
  30. const int64_t kAfterDisplayChangeThrottleTimeoutMs = 500;
  31. const int64_t kCycleDisplayThrottleTimeoutMs = 4000;
  32. const int64_t kSetPrimaryDisplayThrottleTimeoutMs = 500;
  33. bool g_disable_animator_for_test = false;
  34. display::DisplayPositionInUnifiedMatrix GetUnifiedModeShelfCellPosition() {
  35. const ShelfAlignment alignment =
  36. Shell::GetPrimaryRootWindowController()->shelf()->alignment();
  37. switch (alignment) {
  38. case ShelfAlignment::kBottom:
  39. case ShelfAlignment::kBottomLocked:
  40. return display::DisplayPositionInUnifiedMatrix::kBottomLeft;
  41. case ShelfAlignment::kLeft:
  42. return display::DisplayPositionInUnifiedMatrix::kTopLeft;
  43. case ShelfAlignment::kRight:
  44. return display::DisplayPositionInUnifiedMatrix::kTopRight;
  45. }
  46. NOTREACHED();
  47. return display::DisplayPositionInUnifiedMatrix::kBottomLeft;
  48. }
  49. } // namespace
  50. class DisplayConfigurationController::DisplayChangeLimiter {
  51. public:
  52. DisplayChangeLimiter() : throttle_timeout_(base::Time::Now()) {}
  53. DisplayChangeLimiter(const DisplayChangeLimiter&) = delete;
  54. DisplayChangeLimiter& operator=(const DisplayChangeLimiter&) = delete;
  55. void SetThrottleTimeout(int64_t throttle_ms) {
  56. throttle_timeout_ = base::Time::Now() + base::Milliseconds(throttle_ms);
  57. }
  58. bool IsThrottled() const { return base::Time::Now() < throttle_timeout_; }
  59. private:
  60. base::Time throttle_timeout_;
  61. };
  62. // static
  63. void DisplayConfigurationController::DisableAnimatorForTest() {
  64. g_disable_animator_for_test = true;
  65. }
  66. DisplayConfigurationController::DisplayConfigurationController(
  67. display::DisplayManager* display_manager,
  68. WindowTreeHostManager* window_tree_host_manager)
  69. : display_manager_(display_manager),
  70. window_tree_host_manager_(window_tree_host_manager) {
  71. window_tree_host_manager_->AddObserver(this);
  72. if (chromeos::IsRunningAsSystemCompositor())
  73. limiter_ = std::make_unique<DisplayChangeLimiter>();
  74. if (!g_disable_animator_for_test)
  75. display_animator_ = std::make_unique<DisplayAnimator>();
  76. }
  77. DisplayConfigurationController::~DisplayConfigurationController() {
  78. window_tree_host_manager_->RemoveObserver(this);
  79. }
  80. void DisplayConfigurationController::SetDisplayLayout(
  81. std::unique_ptr<display::DisplayLayout> layout) {
  82. if (display_animator_) {
  83. display_animator_->StartFadeOutAnimation(
  84. base::BindOnce(&DisplayConfigurationController::SetDisplayLayoutImpl,
  85. weak_ptr_factory_.GetWeakPtr(), std::move(layout)));
  86. } else {
  87. SetDisplayLayoutImpl(std::move(layout));
  88. }
  89. }
  90. void DisplayConfigurationController::SetUnifiedDesktopLayoutMatrix(
  91. const display::UnifiedDesktopLayoutMatrix& matrix) {
  92. DCHECK(display_manager_->IsInUnifiedMode());
  93. if (display_animator_) {
  94. display_animator_->StartFadeOutAnimation(base::BindOnce(
  95. &DisplayConfigurationController::SetUnifiedDesktopLayoutMatrixImpl,
  96. weak_ptr_factory_.GetWeakPtr(), matrix));
  97. } else {
  98. SetUnifiedDesktopLayoutMatrixImpl(matrix);
  99. }
  100. }
  101. void DisplayConfigurationController::SetMirrorMode(bool mirror, bool throttle) {
  102. if (display_manager_->num_connected_displays() <= 1 ||
  103. display_manager_->IsInMirrorMode() == mirror ||
  104. (throttle && IsLimited())) {
  105. return;
  106. }
  107. SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
  108. if (display_animator_) {
  109. display_animator_->StartFadeOutAnimation(
  110. base::BindOnce(&DisplayConfigurationController::SetMirrorModeImpl,
  111. weak_ptr_factory_.GetWeakPtr(), mirror));
  112. } else {
  113. SetMirrorModeImpl(mirror);
  114. }
  115. }
  116. void DisplayConfigurationController::SetDisplayRotation(
  117. int64_t display_id,
  118. display::Display::Rotation rotation,
  119. display::Display::RotationSource source,
  120. DisplayConfigurationController::RotationAnimation mode) {
  121. // No need to apply animation if the wallpaper isn't set yet during startup.
  122. if (display_manager_->IsDisplayIdValid(display_id) &&
  123. Shell::Get()->wallpaper_controller()->is_wallpaper_set()) {
  124. if (GetTargetRotation(display_id) == rotation)
  125. return;
  126. if (display_animator_) {
  127. ScreenRotationAnimator* screen_rotation_animator =
  128. GetScreenRotationAnimatorForDisplay(display_id);
  129. screen_rotation_animator->Rotate(rotation, source, mode);
  130. return;
  131. }
  132. }
  133. // Invalid |display_id| or animator is disabled; call
  134. // DisplayManager::SetDisplayRotation directly.
  135. display_manager_->SetDisplayRotation(display_id, rotation, source);
  136. }
  137. display::Display::Rotation DisplayConfigurationController::GetTargetRotation(
  138. int64_t display_id) {
  139. if (!display_manager_->IsDisplayIdValid(display_id))
  140. return display::Display::ROTATE_0;
  141. ScreenRotationAnimator* animator =
  142. GetScreenRotationAnimatorForDisplay(display_id);
  143. if (animator->IsRotating())
  144. return animator->GetTargetRotation();
  145. return display_manager_->GetDisplayInfo(display_id).GetActiveRotation();
  146. }
  147. void DisplayConfigurationController::SetPrimaryDisplayId(int64_t display_id,
  148. bool throttle) {
  149. if (display_manager_->GetNumDisplays() <= 1 || (IsLimited() && throttle))
  150. return;
  151. SetThrottleTimeout(kSetPrimaryDisplayThrottleTimeoutMs);
  152. if (display_animator_) {
  153. display_animator_->StartFadeOutAnimation(
  154. base::BindOnce(&DisplayConfigurationController::SetPrimaryDisplayIdImpl,
  155. weak_ptr_factory_.GetWeakPtr(), display_id));
  156. } else {
  157. SetPrimaryDisplayIdImpl(display_id);
  158. }
  159. }
  160. display::Display
  161. DisplayConfigurationController::GetPrimaryMirroringDisplayForUnifiedDesktop()
  162. const {
  163. DCHECK(display_manager_->IsInUnifiedMode());
  164. return display_manager_->GetMirroringDisplayForUnifiedDesktop(
  165. GetUnifiedModeShelfCellPosition());
  166. }
  167. void DisplayConfigurationController::OnDisplayConfigurationChanged() {
  168. // TODO(oshima): Stop all animations.
  169. SetThrottleTimeout(kAfterDisplayChangeThrottleTimeoutMs);
  170. }
  171. // Protected
  172. void DisplayConfigurationController::SetAnimatorForTest(bool enable) {
  173. if (display_animator_ && !enable)
  174. display_animator_.reset();
  175. else if (!display_animator_ && enable)
  176. display_animator_ = std::make_unique<DisplayAnimator>();
  177. }
  178. // Private
  179. void DisplayConfigurationController::SetThrottleTimeout(int64_t throttle_ms) {
  180. if (limiter_)
  181. limiter_->SetThrottleTimeout(throttle_ms);
  182. }
  183. bool DisplayConfigurationController::IsLimited() {
  184. return limiter_ && limiter_->IsThrottled();
  185. }
  186. void DisplayConfigurationController::SetDisplayLayoutImpl(
  187. std::unique_ptr<display::DisplayLayout> layout) {
  188. display_manager_->SetLayoutForCurrentDisplays(std::move(layout));
  189. if (display_animator_)
  190. display_animator_->StartFadeInAnimation();
  191. }
  192. void DisplayConfigurationController::SetMirrorModeImpl(bool mirror) {
  193. display_manager_->SetMirrorMode(
  194. mirror ? display::MirrorMode::kNormal : display::MirrorMode::kOff,
  195. absl::nullopt);
  196. if (display_animator_)
  197. display_animator_->StartFadeInAnimation();
  198. }
  199. void DisplayConfigurationController::SetPrimaryDisplayIdImpl(
  200. int64_t display_id) {
  201. window_tree_host_manager_->SetPrimaryDisplayId(display_id);
  202. if (display_animator_)
  203. display_animator_->StartFadeInAnimation();
  204. }
  205. void DisplayConfigurationController::SetUnifiedDesktopLayoutMatrixImpl(
  206. const display::UnifiedDesktopLayoutMatrix& matrix) {
  207. display_manager_->SetUnifiedDesktopMatrix(matrix);
  208. if (display_animator_)
  209. display_animator_->StartFadeInAnimation();
  210. }
  211. ScreenRotationAnimator*
  212. DisplayConfigurationController::GetScreenRotationAnimatorForDisplay(
  213. int64_t display_id) {
  214. aura::Window* root_window = Shell::GetRootWindowForDisplayId(display_id);
  215. return ScreenRotationAnimator::GetForRootWindow(root_window);
  216. }
  217. } // namespace ash