| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/win/dpi.h" | 5 #include "ui/gfx/win/dpi.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include "base/win/scoped_hdc.h" | 8 #include "base/win/scoped_hdc.h" |
| 9 #include "base/win/windows_version.h" | |
| 10 #include "base/win/registry.h" | |
| 11 #include "ui/gfx/display.h" | 9 #include "ui/gfx/display.h" |
| 12 #include "ui/gfx/point_conversions.h" | 10 #include "ui/gfx/point_conversions.h" |
| 13 #include "ui/gfx/rect_conversions.h" | 11 #include "ui/gfx/rect_conversions.h" |
| 14 #include "ui/gfx/size_conversions.h" | 12 #include "ui/gfx/size_conversions.h" |
| 15 | 13 |
| 16 namespace { | 14 namespace { |
| 17 | 15 |
| 18 int kDefaultDPIX = 96; | 16 int kDefaultDPIX = 96; |
| 19 int kDefaultDPIY = 96; | 17 int kDefaultDPIY = 96; |
| 20 | 18 |
| 21 bool force_highdpi_for_testing = false; | 19 bool force_highdpi_for_testing = false; |
| 22 | 20 |
| 23 BOOL IsProcessDPIAwareWrapper() { | |
| 24 typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID); | |
| 25 IsProcessDPIAwarePtr is_process_dpi_aware_func = | |
| 26 reinterpret_cast<IsProcessDPIAwarePtr>( | |
| 27 GetProcAddress(GetModuleHandleA("user32.dll"), "IsProcessDPIAware")); | |
| 28 if (is_process_dpi_aware_func) | |
| 29 return is_process_dpi_aware_func(); | |
| 30 return FALSE; | |
| 31 } | |
| 32 | |
| 33 float g_device_scale_factor = 0.0f; | 21 float g_device_scale_factor = 0.0f; |
| 34 | 22 |
| 35 float GetUnforcedDeviceScaleFactor() { | 23 float GetUnforcedDeviceScaleFactor() { |
| 36 // If the global device scale factor is initialized use it. This is to ensure | 24 // If the global device scale factor is initialized use it. This is to ensure |
| 37 // we use the same scale factor across all callsites. | 25 // we use the same scale factor across all callsites. |
| 38 if (g_device_scale_factor) | 26 if (g_device_scale_factor) |
| 39 return g_device_scale_factor; | 27 return g_device_scale_factor; |
| 40 return static_cast<float>(gfx::GetDPI().width()) / | 28 return static_cast<float>(gfx::GetDPI().width()) / |
| 41 static_cast<float>(kDefaultDPIX); | 29 static_cast<float>(kDefaultDPIX); |
| 42 } | 30 } |
| 43 | 31 |
| 44 // Duplicated from Win8.1 SDK ShellScalingApi.h | |
| 45 typedef enum PROCESS_DPI_AWARENESS { | |
| 46 PROCESS_DPI_UNAWARE = 0, | |
| 47 PROCESS_SYSTEM_DPI_AWARE = 1, | |
| 48 PROCESS_PER_MONITOR_DPI_AWARE = 2 | |
| 49 } PROCESS_DPI_AWARENESS; | |
| 50 | |
| 51 typedef enum MONITOR_DPI_TYPE { | |
| 52 MDT_EFFECTIVE_DPI = 0, | |
| 53 MDT_ANGULAR_DPI = 1, | |
| 54 MDT_RAW_DPI = 2, | |
| 55 MDT_DEFAULT = MDT_EFFECTIVE_DPI | |
| 56 } MONITOR_DPI_TYPE; | |
| 57 | |
| 58 // Win8.1 supports monitor-specific DPI scaling. | |
| 59 bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) { | |
| 60 typedef BOOL(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS); | |
| 61 SetProcessDpiAwarenessPtr set_process_dpi_awareness_func = | |
| 62 reinterpret_cast<SetProcessDpiAwarenessPtr>( | |
| 63 GetProcAddress(GetModuleHandleA("user32.dll"), | |
| 64 "SetProcessDpiAwarenessInternal")); | |
| 65 if (set_process_dpi_awareness_func) { | |
| 66 HRESULT hr = set_process_dpi_awareness_func(value); | |
| 67 if (SUCCEEDED(hr)) { | |
| 68 VLOG(1) << "SetProcessDpiAwareness succeeded."; | |
| 69 return true; | |
| 70 } else if (hr == E_ACCESSDENIED) { | |
| 71 LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. " | |
| 72 "Function called twice, or manifest was used."; | |
| 73 } | |
| 74 } | |
| 75 return false; | |
| 76 } | |
| 77 | |
| 78 // This function works for Windows Vista through Win8. Win8.1 must use | |
| 79 // SetProcessDpiAwareness[Wrapper] | |
| 80 BOOL SetProcessDPIAwareWrapper() { | |
| 81 typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID); | |
| 82 SetProcessDPIAwarePtr set_process_dpi_aware_func = | |
| 83 reinterpret_cast<SetProcessDPIAwarePtr>( | |
| 84 GetProcAddress(GetModuleHandleA("user32.dll"), | |
| 85 "SetProcessDPIAware")); | |
| 86 return set_process_dpi_aware_func && | |
| 87 set_process_dpi_aware_func(); | |
| 88 } | |
| 89 | |
| 90 DWORD ReadRegistryValue(HKEY root, | |
| 91 const wchar_t* base_key, | |
| 92 const wchar_t* value_name, | |
| 93 DWORD default_value) { | |
| 94 base::win::RegKey reg_key(HKEY_CURRENT_USER, | |
| 95 base_key, | |
| 96 KEY_QUERY_VALUE); | |
| 97 DWORD value; | |
| 98 if (reg_key.Valid() && | |
| 99 reg_key.ReadValueDW(value_name, &value) == ERROR_SUCCESS) { | |
| 100 return value; | |
| 101 } | |
| 102 return default_value; | |
| 103 } | |
| 104 | |
| 105 } // namespace | 32 } // namespace |
| 106 | 33 |
| 107 namespace gfx { | 34 namespace gfx { |
| 108 | 35 |
| 109 void InitDeviceScaleFactor(float scale) { | 36 void InitDeviceScaleFactor(float scale) { |
| 110 DCHECK_NE(0.0f, scale); | 37 DCHECK_NE(0.0f, scale); |
| 111 g_device_scale_factor = scale; | 38 g_device_scale_factor = scale; |
| 112 } | 39 } |
| 113 | 40 |
| 114 Size GetDPI() { | 41 Size GetDPI() { |
| 115 static int dpi_x = 0; | 42 static int dpi_x = 0; |
| 116 static int dpi_y = 0; | 43 static int dpi_y = 0; |
| 117 static bool should_initialize = true; | 44 static bool should_initialize = true; |
| 118 | 45 |
| 119 if (should_initialize) { | 46 if (should_initialize) { |
| 120 should_initialize = false; | 47 should_initialize = false; |
| 121 base::win::ScopedGetDC screen_dc(NULL); | 48 base::win::ScopedGetDC screen_dc(NULL); |
| 122 // This value is safe to cache for the life time of the app since the | 49 // This value is safe to cache for the life time of the app since the |
| 123 // user must logout to change the DPI setting. This value also applies | 50 // user must logout to change the DPI setting. This value also applies |
| 124 // to all screens. | 51 // to all screens. |
| 125 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); | 52 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); |
| 126 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); | 53 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); |
| 127 } | 54 } |
| 128 return Size(dpi_x, dpi_y); | 55 return Size(dpi_x, dpi_y); |
| 129 } | 56 } |
| 130 | 57 |
| 131 float GetDPIScale() { | 58 float GetDPIScale() { |
| 132 if (IsHighDPIEnabled()) { | 59 if (gfx::Display::HasForceDeviceScaleFactor()) |
| 133 if (gfx::Display::HasForceDeviceScaleFactor()) | 60 return gfx::Display::GetForcedDeviceScaleFactor(); |
| 134 return gfx::Display::GetForcedDeviceScaleFactor(); | 61 float dpi_scale = GetUnforcedDeviceScaleFactor(); |
| 135 float dpi_scale = GetUnforcedDeviceScaleFactor(); | 62 if (dpi_scale <= 1.25) { |
| 136 if (dpi_scale <= 1.25) { | 63 // Force 125% and below to 100% scale. We do this to maintain previous |
| 137 // Force 125% and below to 100% scale. We do this to maintain previous | 64 // (non-DPI-aware) behavior where only the font size was boosted. |
| 138 // (non-DPI-aware) behavior where only the font size was boosted. | 65 dpi_scale = 1.0; |
| 139 dpi_scale = 1.0; | |
| 140 } | |
| 141 return dpi_scale; | |
| 142 } | 66 } |
| 143 return 1.0; | 67 return dpi_scale; |
| 144 } | |
| 145 | |
| 146 void ForceHighDPISupportForTesting(float scale) { | |
| 147 g_device_scale_factor = scale; | |
| 148 } | |
| 149 | |
| 150 bool IsHighDPIEnabled() { | |
| 151 // Flag stored in HKEY_CURRENT_USER\SOFTWARE\\Google\\Chrome\\Profile, | |
| 152 // under the DWORD value high-dpi-support. | |
| 153 // Default is disabled. | |
| 154 static DWORD value = ReadRegistryValue( | |
| 155 HKEY_CURRENT_USER, gfx::win::kRegistryProfilePath, | |
| 156 gfx::win::kHighDPISupportW, TRUE); | |
| 157 return value != 0; | |
| 158 } | |
| 159 | |
| 160 void EnableHighDPISupport() { | |
| 161 if (IsHighDPIEnabled() && | |
| 162 !SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) { | |
| 163 SetProcessDPIAwareWrapper(); | |
| 164 } | |
| 165 } | 68 } |
| 166 | 69 |
| 167 namespace win { | 70 namespace win { |
| 168 | 71 |
| 169 GFX_EXPORT const wchar_t kRegistryProfilePath[] = | |
| 170 L"Software\\Google\\Chrome\\Profile"; | |
| 171 GFX_EXPORT const wchar_t kHighDPISupportW[] = L"high-dpi-support"; | |
| 172 | |
| 173 Point ScreenToDIPPoint(const Point& pixel_point) { | 72 Point ScreenToDIPPoint(const Point& pixel_point) { |
| 174 return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDPIScale())); | 73 return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDPIScale())); |
| 175 } | 74 } |
| 176 | 75 |
| 177 Point DIPToScreenPoint(const Point& dip_point) { | 76 Point DIPToScreenPoint(const Point& dip_point) { |
| 178 return ToFlooredPoint(ScalePoint(dip_point, GetDPIScale())); | 77 return ToFlooredPoint(ScalePoint(dip_point, GetDPIScale())); |
| 179 } | 78 } |
| 180 | 79 |
| 181 Rect ScreenToDIPRect(const Rect& pixel_bounds) { | 80 Rect ScreenToDIPRect(const Rect& pixel_bounds) { |
| 182 // It's important we scale the origin and size separately. If we instead | 81 // It's important we scale the origin and size separately. If we instead |
| (...skipping 18 matching lines...) Expand all Loading... |
| 201 | 100 |
| 202 Size DIPToScreenSize(const Size& dip_size) { | 101 Size DIPToScreenSize(const Size& dip_size) { |
| 203 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | 102 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
| 204 return ToCeiledSize(ScaleSize(dip_size, GetDPIScale())); | 103 return ToCeiledSize(ScaleSize(dip_size, GetDPIScale())); |
| 205 } | 104 } |
| 206 | 105 |
| 207 int GetSystemMetricsInDIP(int metric) { | 106 int GetSystemMetricsInDIP(int metric) { |
| 208 return static_cast<int>(GetSystemMetrics(metric) / GetDPIScale() + 0.5); | 107 return static_cast<int>(GetSystemMetrics(metric) / GetDPIScale() + 0.5); |
| 209 } | 108 } |
| 210 | 109 |
| 211 bool IsDeviceScaleFactorSet() { | |
| 212 return g_device_scale_factor != 0.0f; | |
| 213 } | |
| 214 | |
| 215 } // namespace win | 110 } // namespace win |
| 216 } // namespace gfx | 111 } // namespace gfx |
| OLD | NEW |