tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

desktop_configuration.mm (6978B)


      1 /*
      2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/desktop_capture/mac/desktop_configuration.h"
     12 
     13 #include <Cocoa/Cocoa.h>
     14 #include <math.h>
     15 #include <algorithm>
     16 
     17 #include "rtc_base/checks.h"
     18 
     19 namespace webrtc {
     20 
     21 namespace {
     22 
     23 DesktopRect NSRectToDesktopRect(const NSRect& ns_rect) {
     24  return DesktopRect::MakeLTRB(
     25      static_cast<int>(floor(ns_rect.origin.x)),
     26      static_cast<int>(floor(ns_rect.origin.y)),
     27      static_cast<int>(ceil(ns_rect.origin.x + ns_rect.size.width)),
     28      static_cast<int>(ceil(ns_rect.origin.y + ns_rect.size.height)));
     29 }
     30 
     31 // Inverts the position of `rect` from bottom-up coordinates to top-down,
     32 // relative to `bounds`.
     33 void InvertRectYOrigin(const DesktopRect& bounds, DesktopRect* rect) {
     34  RTC_DCHECK_EQ(bounds.top(), 0);
     35  *rect = DesktopRect::MakeXYWH(rect->left(),
     36                                bounds.bottom() - rect->bottom(),
     37                                rect->width(),
     38                                rect->height());
     39 }
     40 
     41 MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) {
     42  MacDisplayConfiguration display_config;
     43 
     44  // Fetch the NSScreenNumber, which is also the CGDirectDisplayID.
     45  NSDictionary* device_description = [screen deviceDescription];
     46  display_config.id = static_cast<CGDirectDisplayID>(
     47      [[device_description objectForKey:@"NSScreenNumber"] intValue]);
     48 
     49  // Determine the display's logical & physical dimensions.
     50  NSRect ns_bounds = [screen frame];
     51  display_config.bounds = NSRectToDesktopRect(ns_bounds);
     52 
     53  display_config.dip_to_pixel_scale = [screen backingScaleFactor];
     54  NSRect ns_pixel_bounds = [screen convertRectToBacking:ns_bounds];
     55  display_config.pixel_bounds = NSRectToDesktopRect(ns_pixel_bounds);
     56 
     57  // Determine if the display is built-in or external.
     58  display_config.is_builtin = CGDisplayIsBuiltin(display_config.id);
     59 
     60  return display_config;
     61 }
     62 
     63 }  // namespace
     64 
     65 MacDisplayConfiguration::MacDisplayConfiguration() = default;
     66 MacDisplayConfiguration::MacDisplayConfiguration(
     67    const MacDisplayConfiguration& other) = default;
     68 MacDisplayConfiguration::MacDisplayConfiguration(
     69    MacDisplayConfiguration&& other) = default;
     70 MacDisplayConfiguration::~MacDisplayConfiguration() = default;
     71 
     72 MacDisplayConfiguration& MacDisplayConfiguration::operator=(
     73    const MacDisplayConfiguration& other) = default;
     74 MacDisplayConfiguration& MacDisplayConfiguration::operator=(
     75    MacDisplayConfiguration&& other) = default;
     76 
     77 MacDesktopConfiguration::MacDesktopConfiguration() = default;
     78 MacDesktopConfiguration::MacDesktopConfiguration(
     79    const MacDesktopConfiguration& other) = default;
     80 MacDesktopConfiguration::MacDesktopConfiguration(
     81    MacDesktopConfiguration&& other) = default;
     82 MacDesktopConfiguration::~MacDesktopConfiguration() = default;
     83 
     84 MacDesktopConfiguration& MacDesktopConfiguration::operator=(
     85    const MacDesktopConfiguration& other) = default;
     86 MacDesktopConfiguration& MacDesktopConfiguration::operator=(
     87    MacDesktopConfiguration&& other) = default;
     88 
     89 // static
     90 MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) {
     91  MacDesktopConfiguration desktop_config;
     92 
     93  NSArray* screens = [NSScreen screens];
     94  RTC_DCHECK(screens);
     95 
     96  // Iterator over the monitors, adding the primary monitor and monitors whose
     97  // DPI match that of the primary monitor.
     98  for (NSUInteger i = 0; i < [screens count]; ++i) {
     99    MacDisplayConfiguration display_config =
    100        GetConfigurationForScreen([screens objectAtIndex:i]);
    101 
    102    if (i == 0)
    103      desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale;
    104 
    105    // Cocoa uses bottom-up coordinates, so if the caller wants top-down then
    106    // we need to invert the positions of secondary monitors relative to the
    107    // primary one (the primary monitor's position is (0,0) in both systems).
    108    if (i > 0 && origin == TopLeftOrigin) {
    109      InvertRectYOrigin(desktop_config.displays[0].bounds,
    110                        &display_config.bounds);
    111      // `display_bounds` is density dependent, so we need to convert the
    112      // primay monitor's position into the secondary monitor's density context.
    113      float scaling_factor = display_config.dip_to_pixel_scale /
    114          desktop_config.displays[0].dip_to_pixel_scale;
    115      DesktopRect primary_bounds = DesktopRect::MakeLTRB(
    116          desktop_config.displays[0].pixel_bounds.left() * scaling_factor,
    117          desktop_config.displays[0].pixel_bounds.top() * scaling_factor,
    118          desktop_config.displays[0].pixel_bounds.right() * scaling_factor,
    119          desktop_config.displays[0].pixel_bounds.bottom() * scaling_factor);
    120      InvertRectYOrigin(primary_bounds, &display_config.pixel_bounds);
    121    }
    122 
    123    // Add the display to the configuration.
    124    desktop_config.displays.push_back(display_config);
    125 
    126    // Update the desktop bounds to account for this display, unless the current
    127    // display uses different DPI settings.
    128    if (display_config.dip_to_pixel_scale ==
    129        desktop_config.dip_to_pixel_scale) {
    130      desktop_config.bounds.UnionWith(display_config.bounds);
    131      desktop_config.pixel_bounds.UnionWith(display_config.pixel_bounds);
    132    }
    133  }
    134 
    135  return desktop_config;
    136 }
    137 
    138 // For convenience of comparing MacDisplayConfigurations in
    139 // MacDesktopConfiguration::Equals.
    140 bool operator==(const MacDisplayConfiguration& left,
    141                const MacDisplayConfiguration& right) {
    142  return left.id == right.id && left.bounds.equals(right.bounds) &&
    143      left.pixel_bounds.equals(right.pixel_bounds) &&
    144      left.dip_to_pixel_scale == right.dip_to_pixel_scale;
    145 }
    146 
    147 bool MacDesktopConfiguration::Equals(const MacDesktopConfiguration& other) {
    148  return bounds.equals(other.bounds) &&
    149      pixel_bounds.equals(other.pixel_bounds) &&
    150      dip_to_pixel_scale == other.dip_to_pixel_scale &&
    151      displays == other.displays;
    152 }
    153 
    154 const MacDisplayConfiguration*
    155    MacDesktopConfiguration::FindDisplayConfigurationById(
    156        CGDirectDisplayID id) {
    157  bool is_builtin = CGDisplayIsBuiltin(id);
    158  for (MacDisplayConfigurations::const_iterator it = displays.begin();
    159       it != displays.end();
    160       ++it) {
    161    // The MBP having both discrete and integrated graphic cards will do
    162    // automate graphics switching by default. When it switches from discrete to
    163    // integrated one, the current display ID of the built-in display will
    164    // change and this will cause screen capture stops.
    165    // So make screen capture of built-in display continuing even if its display
    166    // ID is changed.
    167    if ((is_builtin && it->is_builtin) || (!is_builtin && it->id == id))
    168      return &(*it);
    169  }
    170  return NULL;
    171 }
    172 
    173 }  // namespace webrtc