media/webrtc/trunk/webrtc/modules/desktop_capture/mac/window_list_utils.cc
author Randell Jesup <rjesup@jesup.org>
Tue, 13 Jun 2017 01:54:13 -0400
changeset 414812 cbb06ea384e95b8e33886c0825bee14867a8851b
parent 414811 fda2b2655b267852bfd29fe60a3ca0664c8de18b
child 503443 f40ca921b74b4387d281548d2cd60bbb67e0611c
permissions -rw-r--r--
Bug 1341285: rollup of changes for webrtc after applying webrtc.org v57 update r=ng,jesup,pehrsons,drno,dminor,cpearce,jya,glandium,dmajor Includes re-importing gyp files removed from upstream in v56, and then updating them to match the BUILD.gn file changes.

/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"

#include <ApplicationServices/ApplicationServices.h>

#include "webrtc/base/macutils.h"

namespace webrtc {

bool GetWindowList(DesktopCapturer::SourceList* windows,
                   bool ignore_minimized) {
  // Only get on screen, non-desktop windows.
  CFArrayRef window_array = CGWindowListCopyWindowInfo(
      kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
      kCGNullWindowID);
  if (!window_array)
    return false;

  MacDesktopConfiguration desktop_config;
  if (ignore_minimized) {
    desktop_config = MacDesktopConfiguration::GetCurrent(
        MacDesktopConfiguration::TopLeftOrigin);
  }

  // Check windows to make sure they have an id, title, and use window layer
  // other than 0.
  CFIndex count = CFArrayGetCount(window_array);
  for (CFIndex i = 0; i < count; ++i) {
    CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
        CFArrayGetValueAtIndex(window_array, i));
    CFStringRef window_title = reinterpret_cast<CFStringRef>(
        CFDictionaryGetValue(window, kCGWindowName));
    CFNumberRef window_id = reinterpret_cast<CFNumberRef>(
        CFDictionaryGetValue(window, kCGWindowNumber));
    CFNumberRef window_pid = reinterpret_cast<CFNumberRef>(
        CFDictionaryGetValue(window, kCGWindowOwnerPID));
    CFNumberRef window_layer = reinterpret_cast<CFNumberRef>(
        CFDictionaryGetValue(window, kCGWindowLayer));
    if (window_title && window_id && window_layer) {
      //Skip windows of zero area
      CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
           CFDictionaryGetValue(window,kCGWindowBounds));
      CGRect bounds_rect;
      if(!(bounds_ref) ||
        !(CGRectMakeWithDictionaryRepresentation(bounds_ref,&bounds_rect))){
        continue;
      }
      bounds_rect = CGRectStandardize(bounds_rect);
      if((bounds_rect.size.width <= 0) || (bounds_rect.size.height <= 0)){
        continue;
      }
      // Skip windows with layer=0 (menu, dock).
      int layer;
      CFNumberGetValue(window_layer, kCFNumberIntType, &layer);
      if (layer != 0)
        continue;

      int id;
      CFNumberGetValue(window_id, kCFNumberIntType, &id);
      pid_t pid = 0;
      CFNumberGetValue(window_pid, kCFNumberIntType, &pid);

      // Skip windows that are minimized and not full screen.
      if (ignore_minimized && IsWindowMinimized(id) &&
          !IsWindowFullScreen(desktop_config, window)) {
        continue;
      }

      DesktopCapturer::Source window;
      window.id = id;
      window.pid = pid;
      if (!rtc::ToUtf8(window_title, &(window.title)) ||
          window.title.empty()) {
        continue;
      }
      windows->push_back(window);
    }
  }

  CFRelease(window_array);
  return true;
}

// Returns true if the window is occupying a full screen.
bool IsWindowFullScreen(
    const MacDesktopConfiguration& desktop_config,
    CFDictionaryRef window) {
  bool fullscreen = false;
  CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
      CFDictionaryGetValue(window, kCGWindowBounds));

  CGRect bounds;
  if (bounds_ref &&
      CGRectMakeWithDictionaryRepresentation(bounds_ref, &bounds)) {
    for (MacDisplayConfigurations::const_iterator it =
             desktop_config.displays.begin();
         it != desktop_config.displays.end(); ++it) {
      if (it->bounds.equals(DesktopRect::MakeXYWH(bounds.origin.x,
                                                  bounds.origin.y,
                                                  bounds.size.width,
                                                  bounds.size.height))) {
        fullscreen = true;
        break;
      }
    }
  }

  return fullscreen;
}

// Returns true if the window is minimized.
bool IsWindowMinimized(CGWindowID id) {
  CFArrayRef window_id_array =
      CFArrayCreate(NULL, reinterpret_cast<const void **>(&id), 1, NULL);
  CFArrayRef window_array =
      CGWindowListCreateDescriptionFromArray(window_id_array);
  bool minimized = false;

  if (window_array && CFArrayGetCount(window_array)) {
    CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
        CFArrayGetValueAtIndex(window_array, 0));
    CFBooleanRef on_screen =  reinterpret_cast<CFBooleanRef>(
        CFDictionaryGetValue(window, kCGWindowIsOnscreen));

    minimized = !on_screen;
  }

  CFRelease(window_id_array);
  CFRelease(window_array);

  return minimized;
}



}  // namespace webrtc