| // Copyright (c) 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/display.h" |
| |
| #include <algorithm> |
| |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "build/build_config.h" |
| #include "ui/display/display_switches.h" |
| #include "ui/gfx/geometry/insets.h" |
| #include "ui/gfx/geometry/point_conversions.h" |
| #include "ui/gfx/geometry/point_f.h" |
| #include "ui/gfx/geometry/size_conversions.h" |
| |
| namespace display { |
| namespace { |
| |
| // This variable tracks whether the forced device scale factor switch needs to |
| // be read from the command line, i.e. if it is set to -1 then the command line |
| // is checked. |
| int g_has_forced_device_scale_factor = -1; |
| |
| // This variable caches the forced device scale factor value which is read off |
| // the command line. If the cache is invalidated by setting this variable to |
| // -1.0, we read the forced device scale factor again. |
| float g_forced_device_scale_factor = -1.0; |
| |
| bool HasForceDeviceScaleFactorImpl() { |
| return base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kForceDeviceScaleFactor); |
| } |
| |
| float GetForcedDeviceScaleFactorImpl() { |
| double scale_in_double = 1.0; |
| if (HasForceDeviceScaleFactorImpl()) { |
| std::string value = |
| base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| switches::kForceDeviceScaleFactor); |
| if (!base::StringToDouble(value, &scale_in_double)) { |
| LOG(ERROR) << "Failed to parse the default device scale factor:" << value; |
| scale_in_double = 1.0; |
| } |
| } |
| return static_cast<float>(scale_in_double); |
| } |
| |
| int64_t internal_display_id_ = -1; |
| |
| } // namespace |
| |
| // static |
| float Display::GetForcedDeviceScaleFactor() { |
| if (g_forced_device_scale_factor < 0) |
| g_forced_device_scale_factor = GetForcedDeviceScaleFactorImpl(); |
| return g_forced_device_scale_factor; |
| } |
| |
| // static |
| bool Display::HasForceDeviceScaleFactor() { |
| if (g_has_forced_device_scale_factor == -1) |
| g_has_forced_device_scale_factor = HasForceDeviceScaleFactorImpl(); |
| return !!g_has_forced_device_scale_factor; |
| } |
| |
| // static |
| void Display::ResetForceDeviceScaleFactorForTesting() { |
| g_has_forced_device_scale_factor = -1; |
| g_forced_device_scale_factor = -1.0; |
| } |
| |
| Display::Display() |
| : id_(kInvalidDisplayID), |
| device_scale_factor_(GetForcedDeviceScaleFactor()), |
| rotation_(ROTATE_0), |
| touch_support_(TOUCH_SUPPORT_UNKNOWN) {} |
| |
| Display::Display(const Display& other) = default; |
| |
| Display::Display(int64_t id) |
| : id_(id), |
| device_scale_factor_(GetForcedDeviceScaleFactor()), |
| rotation_(ROTATE_0), |
| touch_support_(TOUCH_SUPPORT_UNKNOWN) {} |
| |
| Display::Display(int64_t id, const gfx::Rect& bounds) |
| : id_(id), |
| bounds_(bounds), |
| work_area_(bounds), |
| device_scale_factor_(GetForcedDeviceScaleFactor()), |
| rotation_(ROTATE_0), |
| touch_support_(TOUCH_SUPPORT_UNKNOWN) { |
| #if defined(USE_AURA) |
| SetScaleAndBounds(device_scale_factor_, bounds); |
| #endif |
| } |
| |
| Display::~Display() {} |
| |
| int Display::RotationAsDegree() const { |
| switch (rotation_) { |
| case ROTATE_0: |
| return 0; |
| case ROTATE_90: |
| return 90; |
| case ROTATE_180: |
| return 180; |
| case ROTATE_270: |
| return 270; |
| } |
| NOTREACHED(); |
| return 0; |
| } |
| |
| void Display::SetRotationAsDegree(int rotation) { |
| switch (rotation) { |
| case 0: |
| rotation_ = ROTATE_0; |
| break; |
| case 90: |
| rotation_ = ROTATE_90; |
| break; |
| case 180: |
| rotation_ = ROTATE_180; |
| break; |
| case 270: |
| rotation_ = ROTATE_270; |
| break; |
| default: |
| // We should not reach that but we will just ignore the call if we do. |
| NOTREACHED(); |
| } |
| } |
| |
| gfx::Insets Display::GetWorkAreaInsets() const { |
| return gfx::Insets(work_area_.y() - bounds_.y(), work_area_.x() - bounds_.x(), |
| bounds_.bottom() - work_area_.bottom(), |
| bounds_.right() - work_area_.right()); |
| } |
| |
| void Display::SetScaleAndBounds(float device_scale_factor, |
| const gfx::Rect& bounds_in_pixel) { |
| gfx::Insets insets = bounds_.InsetsFrom(work_area_); |
| if (!HasForceDeviceScaleFactor()) { |
| #if defined(OS_MACOSX) |
| // Unless an explicit scale factor was provided for testing, ensure the |
| // scale is integral. |
| device_scale_factor = static_cast<int>(device_scale_factor); |
| #endif |
| device_scale_factor_ = device_scale_factor; |
| } |
| device_scale_factor_ = std::max(1.0f, device_scale_factor_); |
| bounds_ = gfx::Rect(gfx::ScaleToFlooredPoint(bounds_in_pixel.origin(), |
| 1.0f / device_scale_factor_), |
| gfx::ScaleToFlooredSize(bounds_in_pixel.size(), |
| 1.0f / device_scale_factor_)); |
| UpdateWorkAreaFromInsets(insets); |
| } |
| |
| void Display::SetSize(const gfx::Size& size_in_pixel) { |
| gfx::Point origin = bounds_.origin(); |
| #if defined(USE_AURA) |
| origin = gfx::ScaleToFlooredPoint(origin, device_scale_factor_); |
| #endif |
| SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel)); |
| } |
| |
| void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) { |
| work_area_ = bounds_; |
| work_area_.Inset(insets); |
| } |
| |
| gfx::Size Display::GetSizeInPixel() const { |
| return gfx::ScaleToFlooredSize(size(), device_scale_factor_); |
| } |
| |
| std::string Display::ToString() const { |
| return base::StringPrintf( |
| "Display[%lld] bounds=%s, workarea=%s, scale=%f, %s", |
| static_cast<long long int>(id_), bounds_.ToString().c_str(), |
| work_area_.ToString().c_str(), device_scale_factor_, |
| IsInternal() ? "internal" : "external"); |
| } |
| |
| bool Display::IsInternal() const { |
| return is_valid() && (id_ == internal_display_id_); |
| } |
| |
| // static |
| int64_t Display::InternalDisplayId() { |
| DCHECK_NE(kInvalidDisplayID, internal_display_id_); |
| return internal_display_id_; |
| } |
| |
| // static |
| void Display::SetInternalDisplayId(int64_t internal_display_id) { |
| internal_display_id_ = internal_display_id; |
| } |
| |
| // static |
| bool Display::IsInternalDisplayId(int64_t display_id) { |
| DCHECK_NE(kInvalidDisplayID, display_id); |
| return HasInternalDisplay() && internal_display_id_ == display_id; |
| } |
| |
| // static |
| bool Display::HasInternalDisplay() { |
| return internal_display_id_ != kInvalidDisplayID; |
| } |
| |
| } // namespace display |