15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Copyright 2010 Google Inc. All Rights Reserved 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/macwindowpicker.h" 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <ApplicationServices/ApplicationServices.h> 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <CoreFoundation/CoreFoundation.h> 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <dlfcn.h> 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h" 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/macutils.h" 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base { 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char* kCoreGraphicsName = 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/" 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org "CoreGraphics.framework/CoreGraphics"; 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char* kWindowListCopyWindowInfo = "CGWindowListCopyWindowInfo"; 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const char* kWindowListCreateDescriptionFromArray = 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org "CGWindowListCreateDescriptionFromArray"; 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Function pointer for holding the CGWindowListCopyWindowInfo function. 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef CFArrayRef(*CGWindowListCopyWindowInfoProc)(CGWindowListOption, 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CGWindowID); 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Function pointer for holding the CGWindowListCreateDescriptionFromArray 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// function. 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgtypedef CFArrayRef(*CGWindowListCreateDescriptionFromArrayProc)(CFArrayRef); 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgMacWindowPicker::MacWindowPicker() : lib_handle_(NULL), get_window_list_(NULL), 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org get_window_list_desc_(NULL) { 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgMacWindowPicker::~MacWindowPicker() { 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (lib_handle_ != NULL) { 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dlclose(lib_handle_); 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::Init() { 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: If this class grows to use more dynamically functions 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // from the CoreGraphics framework, consider using 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // talk/base/latebindingsymboltable.h. 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org lib_handle_ = dlopen(kCoreGraphicsName, RTLD_NOW); 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (lib_handle_ == NULL) { 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Could not load CoreGraphics"; 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org get_window_list_ = dlsym(lib_handle_, kWindowListCopyWindowInfo); 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org get_window_list_desc_ = 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dlsym(lib_handle_, kWindowListCreateDescriptionFromArray); 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (get_window_list_ == NULL || get_window_list_desc_ == NULL) { 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The CGWindowListCopyWindowInfo and the 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // CGWindowListCreateDescriptionFromArray functions was introduced 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // in Leopard(10.5) so this is a normal failure on Tiger. 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Failed to load Core Graphics symbols"; 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org dlclose(lib_handle_); 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org lib_handle_ = NULL; 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::IsVisible(const WindowId& id) { 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Init if we're not already inited. 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (get_window_list_desc_ == NULL && !Init()) { 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CGWindowID ids[1]; 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ids[0] = id.id(); 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayRef window_id_array = 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL); 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayRef window_array = 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org reinterpret_cast<CGWindowListCreateDescriptionFromArrayProc>( 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org get_window_list_desc_)(window_id_array); 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (window_array == NULL || 0 == CFArrayGetCount(window_array)) { 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Could not find the window. It might have been closed. 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Window not found"; 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_id_array); 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>( 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayGetValueAtIndex(window_array, 0)); 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFBooleanRef is_visible = reinterpret_cast<CFBooleanRef>( 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowIsOnscreen)); 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check that the window is visible. If not we might crash. 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool visible = false; 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (is_visible != NULL) { 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org visible = CFBooleanGetValue(is_visible); 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_id_array); 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_array); 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return visible; 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::MoveToFront(const WindowId& id) { 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Init if we're not already initialized. 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (get_window_list_desc_ == NULL && !Init()) { 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CGWindowID ids[1]; 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ids[0] = id.id(); 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayRef window_id_array = 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL); 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayRef window_array = 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org reinterpret_cast<CGWindowListCreateDescriptionFromArrayProc>( 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org get_window_list_desc_)(window_id_array); 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (window_array == NULL || 0 == CFArrayGetCount(window_array)) { 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Could not find the window. It might have been closed. 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Window not found"; 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_id_array); 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>( 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayGetValueAtIndex(window_array, 0)); 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFStringRef window_name_ref = reinterpret_cast<CFStringRef>( 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowName)); 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberRef application_pid = reinterpret_cast<CFNumberRef>( 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowOwnerPID)); 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int pid_val; 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberGetValue(application_pid, kCFNumberIntType, &pid_val); 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string window_name; 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ToUtf8(window_name_ref, &window_name); 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Build an applescript that sets the selected window to front 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // within the application. Then set the application to front. 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool result = true; 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::stringstream ss; 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ss << "tell application \"System Events\"\n" 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "set proc to the first item of (every process whose unix id is " 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << pid_val 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << ")\n" 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "tell proc to perform action \"AXRaise\" of window \"" 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << window_name 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "\"\n" 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "set the frontmost of proc to true\n" 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "end tell"; 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!RunAppleScript(ss.str())) { 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // This might happen to for example X applications where the X 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // server spawns of processes with their own PID but the X server 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // is still registered as owner to the application windows. As a 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // workaround, we put the X server process to front, meaning that 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // all X applications will show up. The drawback with this 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // workaround is that the application that we really wanted to set 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // to front might be behind another X application. 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ProcessSerialNumber psn; 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pid_t pid = pid_val; 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int res = GetProcessForPID(pid, &psn); 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (res != 0) { 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Failed getting process for pid"; 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org result = false; 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org res = SetFrontProcess(&psn); 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (res != 0) { 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Failed setting process to front"; 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org result = false; 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_id_array); 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_array); 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return result; 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::GetDesktopList(DesktopDescriptionList* descriptions) { 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const uint32_t kMaxDisplays = 128; 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CGDirectDisplayID active_displays[kMaxDisplays]; 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint32_t display_count = 0; 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CGError err = CGGetActiveDisplayList(kMaxDisplays, 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org active_displays, 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org &display_count); 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (err != kCGErrorSuccess) { 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG_E(LS_ERROR, OS, err) << "Failed to enumerate the active displays."; 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (uint32_t i = 0; i < display_count; ++i) { 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DesktopId id(active_displays[i], static_cast<int>(i)); 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO: Figure out an appropriate desktop title. 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org DesktopDescription desc(id, ""); 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org desc.set_primary(CGDisplayIsMain(id.id())); 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org descriptions->push_back(desc); 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return display_count > 0; 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::GetDesktopDimensions(const DesktopId& id, 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int* width, 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int* height) { 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *width = CGDisplayPixelsWide(id.id()); 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *height = CGDisplayPixelsHigh(id.id()); 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool MacWindowPicker::GetWindowList(WindowDescriptionList* descriptions) { 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Init if we're not already inited. 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (get_window_list_ == NULL && !Init()) { 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Only get onscreen, non-desktop windows. 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayRef window_array = 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org reinterpret_cast<CGWindowListCopyWindowInfoProc>(get_window_list_)( 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org kCGNullWindowID); 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (window_array == NULL) { 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Check windows to make sure they have an id, title, and use window layer 0. 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFIndex i; 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFIndex count = CFArrayGetCount(window_array); 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (i = 0; i < count; ++i) { 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>( 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFArrayGetValueAtIndex(window_array, i)); 2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFStringRef window_title = reinterpret_cast<CFStringRef>( 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowName)); 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberRef window_id = reinterpret_cast<CFNumberRef>( 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowNumber)); 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberRef window_layer = reinterpret_cast<CFNumberRef>( 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFDictionaryGetValue(window, kCGWindowLayer)); 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (window_title != NULL && window_id != NULL && window_layer != NULL) { 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::string title_str; 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int id_val, layer_val; 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ToUtf8(window_title, &title_str); 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberGetValue(window_id, kCFNumberIntType, &id_val); 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFNumberGetValue(window_layer, kCFNumberIntType, &layer_val); 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Discard windows without a title. 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (layer_val == 0 && title_str.length() > 0) { 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WindowId id(static_cast<CGWindowID>(id_val)); 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org WindowDescription desc(id, title_str); 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org descriptions->push_back(desc); 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CFRelease(window_array); 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace talk_base 251