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 17namespace webrtc { 18 19// The amount of time allowed for displays to reconfigure. 20static const int64_t kDisplayConfigurationEventTimeoutMs = 10 * 1000; 21 22DesktopConfigurationMonitor::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 37DesktopConfigurationMonitor::~DesktopConfigurationMonitor() { 38 CGError err = CGDisplayRemoveReconfigurationCallback( 39 DesktopConfigurationMonitor::DisplaysReconfiguredCallback, this); 40 if (err != kCGErrorSuccess) 41 LOG(LS_ERROR) << "CGDisplayRemoveReconfigurationCallback " << err; 42} 43 44void 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 52void DesktopConfigurationMonitor::Unlock() { 53 display_configuration_capture_event_->Set(); 54} 55 56// static 57void 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 66void 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