display_util.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Copyright 2014 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_util.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <utility>
  8. #include "ash/constants/notifier_catalogs.h"
  9. #include "ash/display/display_configuration_controller.h"
  10. #include "ash/display/extended_mouse_warp_controller.h"
  11. #include "ash/display/null_mouse_warp_controller.h"
  12. #include "ash/display/unified_mouse_warp_controller.h"
  13. #include "ash/host/ash_window_tree_host.h"
  14. #include "ash/public/cpp/new_window_delegate.h"
  15. #include "ash/public/cpp/notification_utils.h"
  16. #include "ash/resources/vector_icons/vector_icons.h"
  17. #include "ash/shell.h"
  18. #include "ash/strings/grit/ash_strings.h"
  19. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  20. #include "base/bind.h"
  21. #include "base/strings/string_number_conversions.h"
  22. #include "base/strings/string_util.h"
  23. #include "base/strings/stringprintf.h"
  24. #include "base/strings/utf_string_conversions.h"
  25. #include "base/system/sys_info.h"
  26. #include "ui/aura/env.h"
  27. #include "ui/aura/window_tree_host.h"
  28. #include "ui/base/l10n/l10n_util.h"
  29. #include "ui/display/display.h"
  30. #include "ui/display/manager/display_layout_store.h"
  31. #include "ui/display/manager/display_manager.h"
  32. #include "ui/display/manager/managed_display_info.h"
  33. #include "ui/gfx/geometry/point.h"
  34. #include "ui/gfx/geometry/rect.h"
  35. #include "ui/gfx/geometry/size_conversions.h"
  36. #include "ui/gfx/paint_vector_icon.h"
  37. #include "ui/message_center/message_center.h"
  38. #include "ui/message_center/notification_list.h"
  39. #include "ui/message_center/public/cpp/notification.h"
  40. #include "ui/message_center/public/cpp/notification_delegate.h"
  41. #include "ui/wm/core/coordinate_conversion.h"
  42. namespace ash {
  43. namespace {
  44. const char kDisplayErrorNotificationId[] = "chrome://settings/display/error";
  45. const char kNotifierDisplayError[] = "ash.display.error";
  46. void ConvertPointFromScreenToNative(aura::WindowTreeHost* host,
  47. gfx::Point* point) {
  48. ::wm::ConvertPointFromScreen(host->window(), point);
  49. host->ConvertDIPToScreenInPixels(point);
  50. }
  51. } // namespace
  52. std::unique_ptr<MouseWarpController> CreateMouseWarpController(
  53. display::DisplayManager* manager,
  54. aura::Window* drag_source) {
  55. if (manager->IsInUnifiedMode() && manager->num_connected_displays() >= 2)
  56. return std::make_unique<UnifiedMouseWarpController>();
  57. // Extra check for |num_connected_displays()| is for SystemDisplayApiTest
  58. // that injects MockScreen.
  59. if (manager->GetNumDisplays() < 2 || manager->num_connected_displays() < 2)
  60. return std::make_unique<NullMouseWarpController>();
  61. return std::make_unique<ExtendedMouseWarpController>(drag_source);
  62. }
  63. gfx::Rect GetNativeEdgeBounds(AshWindowTreeHost* ash_host,
  64. const gfx::Rect& bounds_in_screen) {
  65. aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
  66. gfx::Rect native_bounds = host->GetBoundsInPixels();
  67. native_bounds.Inset(ash_host->GetHostInsets());
  68. gfx::Point start_in_native = bounds_in_screen.origin();
  69. gfx::Point end_in_native = bounds_in_screen.bottom_right();
  70. ConvertPointFromScreenToNative(host, &start_in_native);
  71. ConvertPointFromScreenToNative(host, &end_in_native);
  72. if (std::abs(start_in_native.x() - end_in_native.x()) <
  73. std::abs(start_in_native.y() - end_in_native.y())) {
  74. // vertical in native
  75. int x = std::abs(native_bounds.x() - start_in_native.x()) <
  76. std::abs(native_bounds.right() - start_in_native.x())
  77. ? native_bounds.x()
  78. : native_bounds.right() - 1;
  79. return gfx::Rect(x, std::min(start_in_native.y(), end_in_native.y()), 1,
  80. std::abs(end_in_native.y() - start_in_native.y()));
  81. } else {
  82. // horizontal in native
  83. int y = std::abs(native_bounds.y() - start_in_native.y()) <
  84. std::abs(native_bounds.bottom() - start_in_native.y())
  85. ? native_bounds.y()
  86. : native_bounds.bottom() - 1;
  87. return gfx::Rect(std::min(start_in_native.x(), end_in_native.x()), y,
  88. std::abs(end_in_native.x() - start_in_native.x()), 1);
  89. }
  90. }
  91. // Moves the cursor to the point inside the root that is closest to
  92. // the point_in_screen, which is outside of the root window.
  93. void MoveCursorTo(AshWindowTreeHost* ash_host,
  94. const gfx::Point& point_in_screen,
  95. bool update_last_location_now) {
  96. aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
  97. gfx::Point point_in_native = point_in_screen;
  98. ::wm::ConvertPointFromScreen(host->window(), &point_in_native);
  99. host->ConvertDIPToScreenInPixels(&point_in_native);
  100. // now fit the point inside the native bounds.
  101. gfx::Rect native_bounds = host->GetBoundsInPixels();
  102. gfx::Point native_origin = native_bounds.origin();
  103. native_bounds.Inset(ash_host->GetHostInsets());
  104. // Shrink further so that the mouse doesn't warp on the
  105. // edge. The right/bottom needs to be shrink by 2 to subtract
  106. // the 1 px from width/height value.
  107. native_bounds.Inset(gfx::Insets::TLBR(1, 1, 2, 2));
  108. // Ensure that |point_in_native| is inside the |native_bounds|.
  109. point_in_native.SetToMax(native_bounds.origin());
  110. point_in_native.SetToMin(native_bounds.bottom_right());
  111. gfx::Point point_in_host = point_in_native;
  112. point_in_host.Offset(-native_origin.x(), -native_origin.y());
  113. host->MoveCursorToLocationInPixels(point_in_host);
  114. if (update_last_location_now) {
  115. gfx::Point new_point_in_screen = point_in_native;
  116. host->ConvertScreenInPixelsToDIP(&new_point_in_screen);
  117. ::wm::ConvertPointToScreen(host->window(), &new_point_in_screen);
  118. if (Shell::Get()->display_manager()->IsInUnifiedMode()) {
  119. // In unified desktop mode, the mirroring host converts the point to the
  120. // unified host's pixel coordinates, so we also need to apply the unified
  121. // host transform to get a point in the unified screen coordinates to take
  122. // into account any device scale factors or ui scaling.
  123. Shell::GetPrimaryRootWindow()->GetHost()->ConvertScreenInPixelsToDIP(
  124. &new_point_in_screen);
  125. }
  126. aura::Env::GetInstance()->SetLastMouseLocation(new_point_in_screen);
  127. }
  128. }
  129. void ShowDisplayErrorNotification(const std::u16string& message,
  130. bool allow_feedback) {
  131. // Always remove the notification to make sure the notification appears
  132. // as a popup in any situation.
  133. message_center::MessageCenter::Get()->RemoveNotification(
  134. kDisplayErrorNotificationId, false /* by_user */);
  135. message_center::RichNotificationData data;
  136. if (allow_feedback) {
  137. message_center::ButtonInfo send_button(
  138. l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_SEND_FEEDBACK));
  139. data.buttons.push_back(send_button);
  140. }
  141. std::unique_ptr<message_center::Notification> notification =
  142. CreateSystemNotification(
  143. message_center::NOTIFICATION_TYPE_SIMPLE, kDisplayErrorNotificationId,
  144. std::u16string(), // title
  145. message,
  146. std::u16string(), // display_source
  147. GURL(),
  148. message_center::NotifierId(
  149. message_center::NotifierType::SYSTEM_COMPONENT,
  150. kNotifierDisplayError, NotificationCatalogName::kDisplayError),
  151. data,
  152. base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
  153. base::BindRepeating([](absl::optional<int> button_index) {
  154. if (button_index)
  155. NewWindowDelegate::GetInstance()->OpenFeedbackPage();
  156. })),
  157. kNotificationMonitorWarningIcon,
  158. message_center::SystemNotificationWarningLevel::WARNING);
  159. message_center::MessageCenter::Get()->AddNotification(
  160. std::move(notification));
  161. }
  162. bool IsRectContainedByAnyDisplay(const gfx::Rect& rect_in_screen) {
  163. const std::vector<display::Display>& displays =
  164. display::Screen::GetScreen()->GetAllDisplays();
  165. for (const auto& display : displays) {
  166. if (display.bounds().Contains(rect_in_screen))
  167. return true;
  168. }
  169. return false;
  170. }
  171. std::u16string ConvertRefreshRateToString16(float refresh_rate) {
  172. std::string str = base::StringPrintf("%.2f", refresh_rate);
  173. // Remove the mantissa for whole numbers.
  174. if (EndsWith(str, ".00", base::CompareCase::INSENSITIVE_ASCII))
  175. str.erase(str.length() - 3);
  176. return base::UTF8ToUTF16(str);
  177. }
  178. std::u16string GetDisplayErrorNotificationMessageForTest() {
  179. message_center::NotificationList::Notifications notifications =
  180. message_center::MessageCenter::Get()->GetVisibleNotifications();
  181. for (auto* const notification : notifications) {
  182. if (notification->id() == kDisplayErrorNotificationId)
  183. return notification->message();
  184. }
  185. return std::u16string();
  186. }
  187. bool ShouldUndoRotationForMirror() {
  188. return Shell::Get()->tablet_mode_controller()->is_in_tablet_physical_state();
  189. }
  190. } // namespace ash