File: desktop_display_info_loader_win.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (158 lines) | stat: -rw-r--r-- 5,347 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/desktop_display_info_loader.h"

#include <windows.h>

#include <algorithm>
#include <limits>
#include <vector>

#include "base/compiler_specific.h"
#include "base/strings/utf_string_conversions.h"

namespace remoting {

namespace {

struct PathWithName {
  DISPLAYCONFIG_PATH_INFO path;
  DISPLAYCONFIG_SOURCE_DEVICE_NAME source_device_name;
};

std::vector<DISPLAYCONFIG_PATH_INFO> GetDisplayConfigPathInfos() {
  LONG result;
  do {
    uint32_t path_elements, mode_elements;
    if (::GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_elements,
                                      &mode_elements) != ERROR_SUCCESS) {
      return {};
    }
    std::vector<DISPLAYCONFIG_PATH_INFO> path_infos(path_elements);
    std::vector<DISPLAYCONFIG_MODE_INFO> mode_infos(mode_elements);
    result = ::QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_elements,
                                  path_infos.data(), &mode_elements,
                                  mode_infos.data(), nullptr);
    if (result == ERROR_SUCCESS) {
      path_infos.resize(path_elements);
      return path_infos;
    }
  } while (result == ERROR_INSUFFICIENT_BUFFER);
  return {};
}

std::vector<PathWithName> GetDisplayPathsWithNames() {
  std::vector<PathWithName> result;
  for (const auto& path : GetDisplayConfigPathInfos()) {
    DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name = {};
    source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
    source_name.header.size = sizeof(source_name);
    source_name.header.adapterId = path.sourceInfo.adapterId;
    source_name.header.id = path.sourceInfo.id;
    if (::DisplayConfigGetDeviceInfo(&source_name.header) == ERROR_SUCCESS) {
      result.push_back({path, source_name});
    }
  }
  return result;
}

std::string GetFriendlyDeviceName(const DISPLAYCONFIG_PATH_INFO& path) {
  DISPLAYCONFIG_TARGET_DEVICE_NAME target_name = {};
  target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
  target_name.header.size = sizeof(target_name);
  target_name.header.adapterId = path.targetInfo.adapterId;
  target_name.header.id = path.targetInfo.id;
  if (::DisplayConfigGetDeviceInfo(&target_name.header) == ERROR_SUCCESS) {
    return base::WideToUTF8(target_name.monitorFriendlyDeviceName);
  }
  return std::string();
}

class DesktopDisplayInfoLoaderWin : public DesktopDisplayInfoLoader {
 public:
  DesktopDisplayInfoLoaderWin() = default;
  ~DesktopDisplayInfoLoaderWin() override = default;

  DesktopDisplayInfo GetCurrentDisplayInfo() override;
};

DesktopDisplayInfo DesktopDisplayInfoLoaderWin::GetCurrentDisplayInfo() {
  // Obtain the paths and names of all display devices on the system. This
  // list will be used to lookup the path for each DISPLAY_DEVICE enumerated
  // below. If found, the path is used to obtain the device's friendly name.
  auto paths_with_names = GetDisplayPathsWithNames();

  int32_t lowest_x = std::numeric_limits<int32_t>::max();
  int32_t lowest_y = std::numeric_limits<int32_t>::max();
  std::vector<DisplayGeometry> displays;
  BOOL enum_result = TRUE;
  for (int device_index = 0;; ++device_index) {
    DISPLAY_DEVICE device = {};
    device.cb = sizeof(device);
    enum_result = EnumDisplayDevices(NULL, device_index, &device, 0);

    // |enum_result| is 0 if we have enumerated all devices.
    if (!enum_result) {
      break;
    }

    // We only care about active displays.
    if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
      continue;
    }

    bool is_default = false;
    if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
      is_default = true;
    }

    // Find the path corresponding to this display device. If found, use it to
    // get the friendly name for the device.
    std::string monitor_name;
    for (const auto& entry : paths_with_names) {
      if (UNSAFE_TODO(wcscmp(entry.source_device_name.viewGdiDeviceName,
                             device.DeviceName)) == 0) {
        monitor_name = GetFriendlyDeviceName(entry.path);
        break;
      }
    }

    // Get additional info about device.
    DEVMODE devmode;
    devmode.dmSize = sizeof(devmode);
    EnumDisplaySettingsEx(device.DeviceName, ENUM_CURRENT_SETTINGS, &devmode,
                          0);

    int32_t x = devmode.dmPosition.x;
    int32_t y = devmode.dmPosition.y;
    displays.emplace_back(
        /* id */ device_index, x, y, devmode.dmPelsWidth, devmode.dmPelsHeight,
        /* dpi */ devmode.dmLogPixels, devmode.dmBitsPerPel, is_default,
        monitor_name);

    lowest_x = std::min(x, lowest_x);
    lowest_y = std::min(y, lowest_y);
  }

  // Normalize the displays so the bounding-box's top-left corner is at (0, 0).
  // This matches the coordinate system used by InputInjectorWin, so that
  // the FractionalInputFilter produces correct x,y-coordinates for injection.
  DesktopDisplayInfo result;
  for (DisplayGeometry& info : displays) {
    info.x -= lowest_x;
    info.y -= lowest_y;
    result.AddDisplay(info);
  }
  return result;
}

}  // namespace

// static
std::unique_ptr<DesktopDisplayInfoLoader> DesktopDisplayInfoLoader::Create() {
  return std::make_unique<DesktopDisplayInfoLoaderWin>();
}

}  // namespace remoting