• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2014 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 "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
12 
13 #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h"
14 #include "webrtc/system_wrappers/include/event_wrapper.h"
15 #include "webrtc/system_wrappers/include/logging.h"
16 
17 namespace webrtc {
18 
19 // The amount of time allowed for displays to reconfigure.
20 static const int64_t kDisplayConfigurationEventTimeoutMs = 10 * 1000;
21 
DesktopConfigurationMonitor()22 DesktopConfigurationMonitor::DesktopConfigurationMonitor()
23     : ref_count_(0),
24       display_configuration_capture_event_(EventWrapper::Create()) {
25   CGError err = CGDisplayRegisterReconfigurationCallback(
26       DesktopConfigurationMonitor::DisplaysReconfiguredCallback, this);
27   if (err != kCGErrorSuccess) {
28     LOG(LS_ERROR) << "CGDisplayRegisterReconfigurationCallback " << err;
29     abort();
30   }
31   display_configuration_capture_event_->Set();
32 
33   desktop_configuration_ = MacDesktopConfiguration::GetCurrent(
34       MacDesktopConfiguration::TopLeftOrigin);
35 }
36 
~DesktopConfigurationMonitor()37 DesktopConfigurationMonitor::~DesktopConfigurationMonitor() {
38   CGError err = CGDisplayRemoveReconfigurationCallback(
39       DesktopConfigurationMonitor::DisplaysReconfiguredCallback, this);
40   if (err != kCGErrorSuccess)
41     LOG(LS_ERROR) << "CGDisplayRemoveReconfigurationCallback " << err;
42 }
43 
Lock()44 void DesktopConfigurationMonitor::Lock() {
45   if (!display_configuration_capture_event_->Wait(
46               kDisplayConfigurationEventTimeoutMs)) {
47     LOG_F(LS_ERROR) << "Event wait timed out.";
48     abort();
49   }
50 }
51 
Unlock()52 void DesktopConfigurationMonitor::Unlock() {
53   display_configuration_capture_event_->Set();
54 }
55 
56 // static
DisplaysReconfiguredCallback(CGDirectDisplayID display,CGDisplayChangeSummaryFlags flags,void * user_parameter)57 void DesktopConfigurationMonitor::DisplaysReconfiguredCallback(
58     CGDirectDisplayID display,
59     CGDisplayChangeSummaryFlags flags,
60     void *user_parameter) {
61   DesktopConfigurationMonitor* monitor =
62       reinterpret_cast<DesktopConfigurationMonitor*>(user_parameter);
63   monitor->DisplaysReconfigured(display, flags);
64 }
65 
DisplaysReconfigured(CGDirectDisplayID display,CGDisplayChangeSummaryFlags flags)66 void DesktopConfigurationMonitor::DisplaysReconfigured(
67     CGDirectDisplayID display,
68     CGDisplayChangeSummaryFlags flags) {
69   if (flags & kCGDisplayBeginConfigurationFlag) {
70     if (reconfiguring_displays_.empty()) {
71       // If this is the first display to start reconfiguring then wait on
72       // |display_configuration_capture_event_| to block the capture thread
73       // from accessing display memory until the reconfiguration completes.
74       if (!display_configuration_capture_event_->Wait(
75               kDisplayConfigurationEventTimeoutMs)) {
76         LOG_F(LS_ERROR) << "Event wait timed out.";
77         abort();
78       }
79     }
80     reconfiguring_displays_.insert(display);
81   } else {
82     reconfiguring_displays_.erase(display);
83     if (reconfiguring_displays_.empty()) {
84       desktop_configuration_ = MacDesktopConfiguration::GetCurrent(
85           MacDesktopConfiguration::TopLeftOrigin);
86       display_configuration_capture_event_->Set();
87     }
88   }
89 }
90 
91 }  // namespace webrtc
92