123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/display/display_util.h"
- #include <algorithm>
- #include <memory>
- #include <utility>
- #include "ash/constants/notifier_catalogs.h"
- #include "ash/display/display_configuration_controller.h"
- #include "ash/display/extended_mouse_warp_controller.h"
- #include "ash/display/null_mouse_warp_controller.h"
- #include "ash/display/unified_mouse_warp_controller.h"
- #include "ash/host/ash_window_tree_host.h"
- #include "ash/public/cpp/new_window_delegate.h"
- #include "ash/public/cpp/notification_utils.h"
- #include "ash/resources/vector_icons/vector_icons.h"
- #include "ash/shell.h"
- #include "ash/strings/grit/ash_strings.h"
- #include "ash/wm/tablet_mode/tablet_mode_controller.h"
- #include "base/bind.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/system/sys_info.h"
- #include "ui/aura/env.h"
- #include "ui/aura/window_tree_host.h"
- #include "ui/base/l10n/l10n_util.h"
- #include "ui/display/display.h"
- #include "ui/display/manager/display_layout_store.h"
- #include "ui/display/manager/display_manager.h"
- #include "ui/display/manager/managed_display_info.h"
- #include "ui/gfx/geometry/point.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size_conversions.h"
- #include "ui/gfx/paint_vector_icon.h"
- #include "ui/message_center/message_center.h"
- #include "ui/message_center/notification_list.h"
- #include "ui/message_center/public/cpp/notification.h"
- #include "ui/message_center/public/cpp/notification_delegate.h"
- #include "ui/wm/core/coordinate_conversion.h"
- namespace ash {
- namespace {
- const char kDisplayErrorNotificationId[] = "chrome://settings/display/error";
- const char kNotifierDisplayError[] = "ash.display.error";
- void ConvertPointFromScreenToNative(aura::WindowTreeHost* host,
- gfx::Point* point) {
- ::wm::ConvertPointFromScreen(host->window(), point);
- host->ConvertDIPToScreenInPixels(point);
- }
- } // namespace
- std::unique_ptr<MouseWarpController> CreateMouseWarpController(
- display::DisplayManager* manager,
- aura::Window* drag_source) {
- if (manager->IsInUnifiedMode() && manager->num_connected_displays() >= 2)
- return std::make_unique<UnifiedMouseWarpController>();
- // Extra check for |num_connected_displays()| is for SystemDisplayApiTest
- // that injects MockScreen.
- if (manager->GetNumDisplays() < 2 || manager->num_connected_displays() < 2)
- return std::make_unique<NullMouseWarpController>();
- return std::make_unique<ExtendedMouseWarpController>(drag_source);
- }
- gfx::Rect GetNativeEdgeBounds(AshWindowTreeHost* ash_host,
- const gfx::Rect& bounds_in_screen) {
- aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
- gfx::Rect native_bounds = host->GetBoundsInPixels();
- native_bounds.Inset(ash_host->GetHostInsets());
- gfx::Point start_in_native = bounds_in_screen.origin();
- gfx::Point end_in_native = bounds_in_screen.bottom_right();
- ConvertPointFromScreenToNative(host, &start_in_native);
- ConvertPointFromScreenToNative(host, &end_in_native);
- if (std::abs(start_in_native.x() - end_in_native.x()) <
- std::abs(start_in_native.y() - end_in_native.y())) {
- // vertical in native
- int x = std::abs(native_bounds.x() - start_in_native.x()) <
- std::abs(native_bounds.right() - start_in_native.x())
- ? native_bounds.x()
- : native_bounds.right() - 1;
- return gfx::Rect(x, std::min(start_in_native.y(), end_in_native.y()), 1,
- std::abs(end_in_native.y() - start_in_native.y()));
- } else {
- // horizontal in native
- int y = std::abs(native_bounds.y() - start_in_native.y()) <
- std::abs(native_bounds.bottom() - start_in_native.y())
- ? native_bounds.y()
- : native_bounds.bottom() - 1;
- return gfx::Rect(std::min(start_in_native.x(), end_in_native.x()), y,
- std::abs(end_in_native.x() - start_in_native.x()), 1);
- }
- }
- // Moves the cursor to the point inside the root that is closest to
- // the point_in_screen, which is outside of the root window.
- void MoveCursorTo(AshWindowTreeHost* ash_host,
- const gfx::Point& point_in_screen,
- bool update_last_location_now) {
- aura::WindowTreeHost* host = ash_host->AsWindowTreeHost();
- gfx::Point point_in_native = point_in_screen;
- ::wm::ConvertPointFromScreen(host->window(), &point_in_native);
- host->ConvertDIPToScreenInPixels(&point_in_native);
- // now fit the point inside the native bounds.
- gfx::Rect native_bounds = host->GetBoundsInPixels();
- gfx::Point native_origin = native_bounds.origin();
- native_bounds.Inset(ash_host->GetHostInsets());
- // Shrink further so that the mouse doesn't warp on the
- // edge. The right/bottom needs to be shrink by 2 to subtract
- // the 1 px from width/height value.
- native_bounds.Inset(gfx::Insets::TLBR(1, 1, 2, 2));
- // Ensure that |point_in_native| is inside the |native_bounds|.
- point_in_native.SetToMax(native_bounds.origin());
- point_in_native.SetToMin(native_bounds.bottom_right());
- gfx::Point point_in_host = point_in_native;
- point_in_host.Offset(-native_origin.x(), -native_origin.y());
- host->MoveCursorToLocationInPixels(point_in_host);
- if (update_last_location_now) {
- gfx::Point new_point_in_screen = point_in_native;
- host->ConvertScreenInPixelsToDIP(&new_point_in_screen);
- ::wm::ConvertPointToScreen(host->window(), &new_point_in_screen);
- if (Shell::Get()->display_manager()->IsInUnifiedMode()) {
- // In unified desktop mode, the mirroring host converts the point to the
- // unified host's pixel coordinates, so we also need to apply the unified
- // host transform to get a point in the unified screen coordinates to take
- // into account any device scale factors or ui scaling.
- Shell::GetPrimaryRootWindow()->GetHost()->ConvertScreenInPixelsToDIP(
- &new_point_in_screen);
- }
- aura::Env::GetInstance()->SetLastMouseLocation(new_point_in_screen);
- }
- }
- void ShowDisplayErrorNotification(const std::u16string& message,
- bool allow_feedback) {
- // Always remove the notification to make sure the notification appears
- // as a popup in any situation.
- message_center::MessageCenter::Get()->RemoveNotification(
- kDisplayErrorNotificationId, false /* by_user */);
- message_center::RichNotificationData data;
- if (allow_feedback) {
- message_center::ButtonInfo send_button(
- l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_FAILURE_SEND_FEEDBACK));
- data.buttons.push_back(send_button);
- }
- std::unique_ptr<message_center::Notification> notification =
- CreateSystemNotification(
- message_center::NOTIFICATION_TYPE_SIMPLE, kDisplayErrorNotificationId,
- std::u16string(), // title
- message,
- std::u16string(), // display_source
- GURL(),
- message_center::NotifierId(
- message_center::NotifierType::SYSTEM_COMPONENT,
- kNotifierDisplayError, NotificationCatalogName::kDisplayError),
- data,
- base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
- base::BindRepeating([](absl::optional<int> button_index) {
- if (button_index)
- NewWindowDelegate::GetInstance()->OpenFeedbackPage();
- })),
- kNotificationMonitorWarningIcon,
- message_center::SystemNotificationWarningLevel::WARNING);
- message_center::MessageCenter::Get()->AddNotification(
- std::move(notification));
- }
- bool IsRectContainedByAnyDisplay(const gfx::Rect& rect_in_screen) {
- const std::vector<display::Display>& displays =
- display::Screen::GetScreen()->GetAllDisplays();
- for (const auto& display : displays) {
- if (display.bounds().Contains(rect_in_screen))
- return true;
- }
- return false;
- }
- std::u16string ConvertRefreshRateToString16(float refresh_rate) {
- std::string str = base::StringPrintf("%.2f", refresh_rate);
- // Remove the mantissa for whole numbers.
- if (EndsWith(str, ".00", base::CompareCase::INSENSITIVE_ASCII))
- str.erase(str.length() - 3);
- return base::UTF8ToUTF16(str);
- }
- std::u16string GetDisplayErrorNotificationMessageForTest() {
- message_center::NotificationList::Notifications notifications =
- message_center::MessageCenter::Get()->GetVisibleNotifications();
- for (auto* const notification : notifications) {
- if (notification->id() == kDisplayErrorNotificationId)
- return notification->message();
- }
- return std::u16string();
- }
- bool ShouldUndoRotationForMirror() {
- return Shell::Get()->tablet_mode_controller()->is_in_tablet_physical_state();
- }
- } // namespace ash
|