| // Copyright 2012 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 "ui/display/screen.h" |
| |
| #include <utility> |
| |
| #include "base/check.h" |
| #include "base/containers/contains.h" |
| #include "base/notreached.h" |
| #include "base/time/time.h" |
| #include "ui/display/display.h" |
| #include "ui/display/types/display_constants.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| namespace display { |
| |
| namespace { |
| |
| Screen* g_screen; |
| |
| } // namespace |
| |
| Screen::Screen() : display_id_for_new_windows_(kInvalidDisplayId) {} |
| |
| Screen::~Screen() = default; |
| |
| // static |
| Screen* Screen::GetScreen() { |
| #if defined(OS_APPLE) |
| // TODO(scottmg): https://crbug.com/558054 |
| if (!g_screen) |
| g_screen = CreateNativeScreen(); |
| #endif |
| return g_screen; |
| } |
| |
| // static |
| Screen* Screen::SetScreenInstance(Screen* instance) { |
| return std::exchange(g_screen, instance); |
| } |
| |
| void Screen::SetCursorScreenPointForTesting(const gfx::Point& point) { |
| NOTIMPLEMENTED_LOG_ONCE(); |
| } |
| |
| Display Screen::GetDisplayNearestView(gfx::NativeView view) const { |
| return GetDisplayNearestWindow(GetWindowForView(view)); |
| } |
| |
| display::Display Screen::GetDisplayForNewWindows() const { |
| display::Display display; |
| // Scoped value can override if it is set. |
| if (scoped_display_id_for_new_windows_ != kInvalidDisplayId && |
| GetDisplayWithDisplayId(scoped_display_id_for_new_windows_, &display)) { |
| return display; |
| } |
| |
| if (GetDisplayWithDisplayId(display_id_for_new_windows_, &display)) |
| return display; |
| |
| // Fallback to primary display. |
| return GetPrimaryDisplay(); |
| } |
| |
| void Screen::SetDisplayForNewWindows(int64_t display_id) { |
| // GetDisplayForNewWindows() handles invalid display ids. |
| display_id_for_new_windows_ = display_id; |
| } |
| |
| DisplayList Screen::GetDisplayListNearestViewWithFallbacks( |
| gfx::NativeView view) const { |
| return GetDisplayListNearestDisplayWithFallbacks(GetDisplayNearestView(view)); |
| } |
| |
| DisplayList Screen::GetDisplayListNearestWindowWithFallbacks( |
| gfx::NativeWindow window) const { |
| return GetDisplayListNearestDisplayWithFallbacks( |
| GetDisplayNearestWindow(window)); |
| } |
| |
| void Screen::SetScreenSaverSuspended(bool suspend) { |
| NOTIMPLEMENTED_LOG_ONCE(); |
| } |
| |
| bool Screen::IsScreenSaverActive() const { |
| NOTIMPLEMENTED_LOG_ONCE(); |
| return false; |
| } |
| |
| base::TimeDelta Screen::CalculateIdleTime() const { |
| NOTIMPLEMENTED_LOG_ONCE(); |
| return base::TimeDelta::FromSeconds(0); |
| } |
| |
| gfx::Rect Screen::ScreenToDIPRectInWindow(gfx::NativeWindow window, |
| const gfx::Rect& screen_rect) const { |
| float scale = GetDisplayNearestWindow(window).device_scale_factor(); |
| return ScaleToEnclosingRect(screen_rect, 1.0f / scale); |
| } |
| |
| gfx::Rect Screen::DIPToScreenRectInWindow(gfx::NativeWindow window, |
| const gfx::Rect& dip_rect) const { |
| float scale = GetDisplayNearestWindow(window).device_scale_factor(); |
| return ScaleToEnclosingRect(dip_rect, scale); |
| } |
| |
| bool Screen::GetDisplayWithDisplayId(int64_t display_id, |
| Display* display) const { |
| for (const Display& display_in_list : GetAllDisplays()) { |
| if (display_in_list.id() == display_id) { |
| *display = display_in_list; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void Screen::SetPanelRotationForTesting(int64_t display_id, |
| Display::Rotation rotation) { |
| // Not implemented. |
| DCHECK(false); |
| } |
| |
| std::string Screen::GetCurrentWorkspace() { |
| NOTIMPLEMENTED_LOG_ONCE(); |
| return {}; |
| } |
| |
| base::Value Screen::GetGpuExtraInfoAsListValue( |
| const gfx::GpuExtraInfo& gpu_extra_info) { |
| return base::Value(base::Value::Type::LIST); |
| } |
| |
| void Screen::SetScopedDisplayForNewWindows(int64_t display_id) { |
| if (display_id == scoped_display_id_for_new_windows_) |
| return; |
| // Only allow set and clear, not switch. |
| DCHECK(display_id == kInvalidDisplayId ^ |
| scoped_display_id_for_new_windows_ == kInvalidDisplayId) |
| << "display_id=" << display_id << ", scoped_display_id_for_new_windows_=" |
| << scoped_display_id_for_new_windows_; |
| scoped_display_id_for_new_windows_ = display_id; |
| } |
| |
| DisplayList Screen::GetDisplayListNearestDisplayWithFallbacks( |
| Display nearest) const { |
| DisplayList display_list; |
| const std::vector<Display>& displays = GetAllDisplays(); |
| Display primary = GetPrimaryDisplay(); |
| if (displays.empty()) { |
| // The nearest display's metrics are of greater value to clients of this |
| // function than those of the primary display, so prefer to use that Display |
| // object as the fallback, if GetAllDisplays() returned an empty array. |
| if (nearest.id() == kInvalidDisplayId && primary.id() != kInvalidDisplayId) |
| display_list = DisplayList({primary}, primary.id(), primary.id()); |
| else |
| display_list = DisplayList({nearest}, nearest.id(), nearest.id()); |
| } else { |
| // Use the primary and nearest displays as fallbacks for each other, if the |
| // counterpart exists in `displays`. Otherwise, use `display[0]` for both. |
| int64_t primary_id = primary.id(); |
| int64_t nearest_id = nearest.id(); |
| const bool has_primary = base::Contains(displays, primary_id, &Display::id); |
| const bool has_nearest = base::Contains(displays, nearest_id, &Display::id); |
| if (!has_primary) |
| primary_id = has_nearest ? nearest_id : displays[0].id(); |
| if (!has_nearest) |
| nearest_id = primary_id; |
| display_list = DisplayList(displays, primary_id, nearest_id); |
| } |
| CHECK(display_list.IsValidAndHasPrimaryAndCurrentDisplays()); |
| return display_list; |
| } |
| |
| } // namespace display |