1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/metrics/ui/screen_info_metrics_provider.h"
6
7 #include <algorithm>
8
9 #include "build/build_config.h"
10 #include "third_party/metrics_proto/system_profile.pb.h"
11 #include "ui/display/display.h"
12 #include "ui/display/screen.h"
13
14 #if BUILDFLAG(IS_WIN)
15 #include <windows.h>
16 #endif
17
18 namespace metrics {
19
20 #if BUILDFLAG(IS_WIN)
21
22 namespace {
23
24 struct ScreenDPIInformation {
25 double max_dpi_x;
26 double max_dpi_y;
27 };
28
29 // Called once for each connected monitor.
GetMonitorDPICallback(HMONITOR,HDC hdc,LPRECT,LPARAM dwData)30 BOOL CALLBACK GetMonitorDPICallback(HMONITOR, HDC hdc, LPRECT, LPARAM dwData) {
31 const double kMillimetersPerInch = 25.4;
32 ScreenDPIInformation* screen_info =
33 reinterpret_cast<ScreenDPIInformation*>(dwData);
34 // Size of screen, in mm.
35 DWORD size_x = GetDeviceCaps(hdc, HORZSIZE);
36 DWORD size_y = GetDeviceCaps(hdc, VERTSIZE);
37 double dpi_x = (size_x > 0) ?
38 GetDeviceCaps(hdc, HORZRES) / (size_x / kMillimetersPerInch) : 0;
39 double dpi_y = (size_y > 0) ?
40 GetDeviceCaps(hdc, VERTRES) / (size_y / kMillimetersPerInch) : 0;
41 screen_info->max_dpi_x = std::max(dpi_x, screen_info->max_dpi_x);
42 screen_info->max_dpi_y = std::max(dpi_y, screen_info->max_dpi_y);
43 return TRUE;
44 }
45
WriteScreenDPIInformationProto(SystemProfileProto::Hardware * hardware)46 void WriteScreenDPIInformationProto(SystemProfileProto::Hardware* hardware) {
47 HDC desktop_dc = GetDC(nullptr);
48 if (desktop_dc) {
49 ScreenDPIInformation si = {0, 0};
50 if (EnumDisplayMonitors(desktop_dc, nullptr, GetMonitorDPICallback,
51 reinterpret_cast<LPARAM>(&si))) {
52 hardware->set_max_dpi_x(si.max_dpi_x);
53 hardware->set_max_dpi_y(si.max_dpi_y);
54 }
55 ReleaseDC(GetDesktopWindow(), desktop_dc);
56 }
57 }
58
59 } // namespace
60
61 #endif // BUILDFLAG(IS_WIN)
62
ScreenInfoMetricsProvider()63 ScreenInfoMetricsProvider::ScreenInfoMetricsProvider() {
64 }
65
~ScreenInfoMetricsProvider()66 ScreenInfoMetricsProvider::~ScreenInfoMetricsProvider() {
67 }
68
ProvideSystemProfileMetrics(SystemProfileProto * system_profile_proto)69 void ScreenInfoMetricsProvider::ProvideSystemProfileMetrics(
70 SystemProfileProto* system_profile_proto) {
71 // This may be called before the screen info has been initialized, such as
72 // when the persistent system profile gets filled in initially.
73 const std::optional<gfx::Size> display_size = GetScreenSize();
74 if (!display_size.has_value())
75 return;
76
77 SystemProfileProto::Hardware* hardware =
78 system_profile_proto->mutable_hardware();
79
80 hardware->set_primary_screen_width(display_size->width());
81 hardware->set_primary_screen_height(display_size->height());
82 hardware->set_primary_screen_scale_factor(GetScreenDeviceScaleFactor());
83 hardware->set_screen_count(GetScreenCount());
84
85 #if BUILDFLAG(IS_WIN)
86 WriteScreenDPIInformationProto(hardware);
87 #endif
88 }
89
GetScreenSize() const90 std::optional<gfx::Size> ScreenInfoMetricsProvider::GetScreenSize() const {
91 auto* screen = display::Screen::GetScreen();
92 if (!screen)
93 return std::nullopt;
94 return std::make_optional(screen->GetPrimaryDisplay().GetSizeInPixel());
95 }
96
GetScreenDeviceScaleFactor() const97 float ScreenInfoMetricsProvider::GetScreenDeviceScaleFactor() const {
98 return display::Screen::GetScreen()
99 ->GetPrimaryDisplay()
100 .device_scale_factor();
101 }
102
GetScreenCount() const103 int ScreenInfoMetricsProvider::GetScreenCount() const {
104 return display::Screen::GetScreen()->GetNumDisplays();
105 }
106
107 } // namespace metrics
108