|
// |
|
// ShareScreenMac.mm |
|
// ShareScreenLib |
|
// |
|
// Created by Rick Cheng on 4/17/20. |
|
// Copyright © 2020 Agora. All rights reserved. |
|
// |
|
|
|
#import <Foundation/Foundation.h> |
|
#import <AppKit/AppKit.h> |
|
#import <CoreGraphics/CoreGraphics.h> |
|
|
|
#if _MSC_VER // this is defined when compiling with Visual Studio |
|
#define EXPORT_API __declspec(dllexport) // Visual Studio needs annotating exported functions with this |
|
#else |
|
#define EXPORT_API // XCode does not need annotating exported functions, so define is empty |
|
#endif |
|
|
|
// ------------------------------------------------------------------------ |
|
// Plugin itself |
|
|
|
|
|
// Link following functions C-style (required for plugins) |
|
extern "C" |
|
{ |
|
// Just a test |
|
EXPORT_API int PrintANumber(){ |
|
return 7; |
|
} |
|
|
|
/// Obtain a list of DisplayIds |
|
/// @param d - managed array passed from C# layer |
|
/// @param size - assigned elements in the array |
|
/// @param length - array length |
|
EXPORT_API void GetDisplayIds(unsigned int * d, int * size, int length) |
|
{ |
|
int count = 0; |
|
for(NSScreen *screen in [NSScreen screens]) |
|
{ |
|
NSDictionary * dict = [screen deviceDescription]; |
|
NSNumber * ddd = (NSNumber *) dict[@"NSScreenNumber"]; |
|
|
|
if (ddd != nil) |
|
{ |
|
UInt displayId = [ddd unsignedIntValue]; |
|
d[count] = displayId; |
|
} |
|
count++; |
|
if (count > length) break; |
|
} |
|
|
|
*size = count; |
|
} |
|
|
|
|
|
|
|
/// Obtain a list of Windows information |
|
/// @param output - A preallocated memory buffer to hold string data, represents windows list array in JSON format |
|
/// @param capacity - the length of the output allocated |
|
EXPORT_API void GetWindows(char * output, int capacity) |
|
{ |
|
NSArray* windows = (NSArray*)CFBridgingRelease(CGWindowListCopyWindowInfo( |
|
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID)); |
|
|
|
// NSLog(@"All on screen windows: %lu\n", (unsigned long)windows.count); |
|
|
|
// The windows filled, but we should filter out anything below the dock area |
|
// Find window ID of "Dock" window |
|
NSNumber *dockWindowNumber = nil; |
|
for (NSDictionary *window in windows) { |
|
if ([(NSString *)window[(__bridge NSString *)kCGWindowName] isEqualToString:@"Dock"]) { |
|
dockWindowNumber = window[(__bridge NSString *)kCGWindowNumber]; |
|
break; |
|
} |
|
} |
|
// NSLog(@"dockWindowNumber: %@\n", dockWindowNumber); |
|
|
|
if (dockWindowNumber) { |
|
// Fetch on screen windows again, filtering to those "below" the Dock window |
|
// This filters out all but the "standard" application windows |
|
CFArrayRef windowListArray = CGWindowListCreate(kCGWindowListOptionOnScreenBelowWindow|kCGWindowListExcludeDesktopElements, [dockWindowNumber unsignedIntValue]); |
|
windows = CFBridgingRelease(CGWindowListCreateDescriptionFromArray(windowListArray)); |
|
// NSLog(@"On screen application windows: %@", windows); |
|
CFRelease(windowListArray); |
|
} |
|
else { |
|
// NSLog(@"Could not find Dock window description"); |
|
} |
|
|
|
// Turn the list into a JSON string to return |
|
NSError *error = nil; |
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:windows options:0 error:&error]; |
|
NSString *jsonString = [[NSString alloc] initWithData:jsonData |
|
encoding:NSUTF8StringEncoding]; |
|
|
|
// NSLog(@"JSON: %@\n", jsonString); |
|
|
|
NSUInteger length = [jsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; |
|
if ( length >0 && length < capacity) { |
|
strcpy(output, jsonString.UTF8String); |
|
} else { |
|
NSLog(@"The output string can't hold the JSON:%ld", length); |
|
} |
|
} |
|
} // end of export C block |