File: desktop_display_info.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 (239 lines) | stat: -rw-r--r-- 8,051 bytes parent folder | download | duplicates (6)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// Copyright 2018 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.h"

#include "base/check.h"
#include "build/build_config.h"
#include "remoting/base/constants.h"
#include "remoting/base/logging.h"
#include "remoting/proto/control.pb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"

namespace remoting {

DisplayGeometry::DisplayGeometry() = default;
DisplayGeometry::DisplayGeometry(webrtc::ScreenId id,
                                 int32_t x,
                                 int32_t y,
                                 uint32_t width,
                                 uint32_t height,
                                 uint32_t dpi,
                                 uint32_t bpp,
                                 bool is_default,
                                 const std::string& display_name)
    : id(id),
      x(x),
      y(y),
      width(width),
      height(height),
      dpi(dpi),
      bpp(bpp),
      is_default(is_default),
      display_name(display_name) {}

DisplayGeometry::DisplayGeometry(const DisplayGeometry&) = default;
DisplayGeometry& DisplayGeometry::operator=(const DisplayGeometry&) = default;
DisplayGeometry::~DisplayGeometry() = default;

DesktopDisplayInfo::DesktopDisplayInfo() = default;
DesktopDisplayInfo::DesktopDisplayInfo(DesktopDisplayInfo&&) = default;
DesktopDisplayInfo& DesktopDisplayInfo::operator=(DesktopDisplayInfo&&) =
    default;
DesktopDisplayInfo::~DesktopDisplayInfo() = default;

bool DesktopDisplayInfo::operator==(const DesktopDisplayInfo& other) const {
  if (other.displays_.size() == displays_.size()) {
    for (size_t display = 0; display < displays_.size(); display++) {
      const DisplayGeometry& this_display = displays_[display];
      const DisplayGeometry& other_display = other.displays_[display];
      if (this_display.id != other_display.id ||
          this_display.x != other_display.x ||
          this_display.y != other_display.y ||
          this_display.width != other_display.width ||
          this_display.height != other_display.height ||
          this_display.dpi != other_display.dpi ||
          this_display.bpp != other_display.bpp ||
          this_display.is_default != other_display.is_default ||
          this_display.display_name != other_display.display_name) {
        return false;
      }
    }
    return true;
  }
  return false;
}

bool DesktopDisplayInfo::operator!=(const DesktopDisplayInfo& other) const {
  return !(*this == other);
}

/* static */
webrtc::DesktopSize DesktopDisplayInfo::CalcSizeDips(webrtc::DesktopSize size,
                                                     int dpi_x,
                                                     int dpi_y) {
  // Guard against invalid input.
  // TODO: Replace with a DCHECK, once crbug.com/938648 is fixed.
  if (dpi_x == 0) {
    dpi_x = kDefaultDpi;
  }
  if (dpi_y == 0) {
    dpi_y = kDefaultDpi;
  }

  webrtc::DesktopSize size_dips(size.width() * kDefaultDpi / dpi_x,
                                size.height() * kDefaultDpi / dpi_y);
  return size_dips;
}

void DesktopDisplayInfo::Reset() {
  displays_.clear();
}

int DesktopDisplayInfo::NumDisplays() const {
  return displays_.size();
}

const DisplayGeometry* DesktopDisplayInfo::GetDisplayInfo(
    unsigned int id) const {
  if (id < 0 || id >= displays_.size()) {
    return nullptr;
  }
  return &displays_[id];
}

// Calculate the offset from the origin of the desktop to the origin of the
// specified display.
//
// For Mac and ChromeOS, the origin of the desktop is the origin of the default
// display.
//
// For Windows/Linux, the origin of the desktop is the upper-left of the
// entire desktop region.
//
// x         b-----------+            ---
//           |           |             |  y-offset to c
// a---------+           |             |
// |         +-------c---+-------+    ---
// |         |       |           |
// +---------+       |           |
//                   +-----------+
//
// |-----------------|
//    x-offset to c
//
// x = upper left of desktop
// a,b,c = origin of display A,B,C
webrtc::DesktopVector DesktopDisplayInfo::CalcDisplayOffset(
    webrtc::ScreenId disp_id) const {
  bool full_desktop = (disp_id == webrtc::kFullDesktopScreenId);
  unsigned int disp_index = disp_id;

  if (full_desktop) {
#if BUILDFLAG(IS_APPLE)
    // For Mac, we need to calculate the offset relative to the default
    // display.
    disp_index = 0;
#else
    // For other platforms, the origin for full desktop is 0,0.
    return webrtc::DesktopVector();
#endif  // !BUILDFLAG(IS_APPLE)
  }

  if (displays_.size() == 0) {
    LOG(INFO) << "No display info available";
    return webrtc::DesktopVector();
  }
  if (disp_index >= displays_.size()) {
    LOG(INFO) << "Invalid display id for CalcDisplayOffset: " << disp_index;
    return webrtc::DesktopVector();
  }

  const DisplayGeometry& disp_info = displays_[disp_index];
  webrtc::DesktopVector origin(disp_info.x, disp_info.y);

  // Find topleft-most display coordinate. This is the topleft of the desktop.
  int dx = 0;
  int dy = 0;
  for (const auto& display : displays_) {
    if (display.x < dx) {
      dx = display.x;
    }
    if (display.y < dy) {
      dy = display.y;
    }
  }
  webrtc::DesktopVector topleft(dx, dy);

#if BUILDFLAG(IS_APPLE)
  // Mac display offsets need to be relative to the main display's origin.
  if (full_desktop) {
    // For full desktop, this is the offset to the topleft display coord.
    return topleft;
  } else {
    // For single displays, this offset is stored in the DisplayGeometry
    // x,y values.
    return origin;
  }
#elif BUILDFLAG(IS_CHROMEOS)
  // ChromeOS display offsets need to be relative to the main display's origin,
  // which is stored in the DisplayGeometry x,y values.
  return origin;
#else
  // Return offset to this screen, relative to topleft.
  return origin.subtract(topleft);
#endif  // BUILDFLAG(IS_APPLE)
}

void DesktopDisplayInfo::AddDisplay(const DisplayGeometry& display) {
  displays_.push_back(display);
}

void DesktopDisplayInfo::AddDisplayFrom(
    const protocol::VideoTrackLayout& track) {
  DisplayGeometry display;
  displays_.emplace_back(track.screen_id(), track.position_x(),
                         track.position_y(), track.width(), track.height(),
                         /* dpi */ track.x_dpi(),
                         /* bpp */ 24,
                         /* is_default */ false, track.display_name());
}

std::unique_ptr<protocol::VideoLayout> DesktopDisplayInfo::GetVideoLayoutProto()
    const {
  auto layout = std::make_unique<protocol::VideoLayout>();
  HOST_LOG << "Displays loaded:";
  for (const auto& display : displays()) {
    protocol::VideoTrackLayout* track = layout->add_video_track();
    track->set_position_x(display.x);
    track->set_position_y(display.y);
    track->set_width(display.width);
    track->set_height(display.height);
    track->set_x_dpi(display.dpi);
    track->set_y_dpi(display.dpi);
    track->set_screen_id(display.id);
    track->set_display_name(display.display_name);
    HOST_LOG << "   Display: " << display.x << "," << display.y << " "
             << display.width << "x" << display.height << " @ " << display.dpi
             << ", id=" << display.id << ", bpp=" << display.bpp
             << ", primary=" << display.is_default
             << ", display_name=" << display.display_name;
    if (display.is_default) {
      if (layout->has_primary_screen_id()) {
        LOG(WARNING) << "Multiple primary displays found";
      }
      layout->set_primary_screen_id(display.id);
    }
  }
  return layout;
}

std::ostream& operator<<(std::ostream& out, const DisplayGeometry& geo) {
  out << "Display " << geo.id << (geo.is_default ? " (primary)" : "") << ": "
      << geo.x << "+" << geo.y << "-" << geo.width << "x" << geo.height << " @ "
      << geo.dpi << " - " << geo.display_name;
  return out;
}

}  // namespace remoting