Created
August 28, 2018 10:37
-
-
Save MarcosCobena/b4768bacc1a112a4f38a9d11a19f1251 to your computer and use it in GitHub Desktop.
A workaround to take screenshots under macOS when Gtk# crashes doing the same (https://github.com/mono/gtk-sharp/issues/236)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using AppKit; | |
using CoreGraphics; | |
using Foundation; | |
using ImageIO; | |
using MobileCoreServices; | |
namespace ScreenshotDemo | |
{ | |
// NOTE Follow https://docs.microsoft.com/es-es/xamarin/mac/app-fundamentals/console to include Xamarin.Mac head-less dependencies | |
public static class MacOSScreenshot | |
{ | |
private const string _appServicesPath = | |
"/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices"; | |
// https://developer.apple.com/documentation/coregraphics/1454603-cggetactivedisplaylist | |
[DllImport(_appServicesPath, EntryPoint = "CGGetActiveDisplayList")] | |
private static extern int CGGetActiveDisplayList(int maxDisplays, int[] activeDisplays, out int displayCount); | |
// https://developer.apple.com/documentation/coregraphics/1455691-cgdisplaycreateimage | |
[DllImport(_appServicesPath, EntryPoint = "CGDisplayCreateImage")] | |
private static extern /* CGImageRef */ IntPtr CGDisplayCreateImage(int displayId); | |
// Based on: https://stackoverflow.com/a/40864231 | |
public static void Take() | |
{ | |
NSApplication.Init(); | |
var result = CGGetActiveDisplayList(0, null, out int displayCount); | |
// https://developer.apple.com/documentation/coregraphics/cgerror/success | |
if (result != 0) | |
{ | |
Console.WriteLine("Error retrieving the displays count."); | |
return; | |
} | |
var allocated = displayCount; | |
// CGDirectDisplayID is an Int32: https://developer.apple.com/documentation/coregraphics/cgdirectdisplayid | |
var activeDisplays = new int[allocated]; // UnsafeMutablePointer<CGDirectDisplayID>.allocate(capacity: allocated) | |
result = CGGetActiveDisplayList(displayCount, activeDisplays, out displayCount); | |
if (result != 0) | |
{ | |
Console.WriteLine("Error retrieving the displays list."); | |
return; | |
} | |
for (int i = 0; i < displayCount; i++) | |
{ | |
var handle = CGDisplayCreateImage(activeDisplays[i]); | |
var screenShot = new CGImage(handle); | |
//let bitmapRep = NSBitmapImageRep(cgImage: screenShot) | |
//let jpegData = bitmapRep.representation(using: NSBitmapImageFileType.JPEG, properties: [:])! | |
#if DEBUG | |
Save(screenShot, $"/Users/marcos/Desktop/screenshot-{i}"); | |
#endif | |
} | |
} | |
// It returns 1x1 px screenshots :-S | |
// Based on: https://stackoverflow.com/q/45714609 | |
// public static void Take() | |
// { | |
// var screens = NSScreen.Screens; | |
// for (int i = 0; i < screens.Length; i++) | |
// { | |
// var item = screens[i]; | |
// var screenshot = CGImage.ScreenImage(i, item.Frame); | |
//#if DEBUG | |
// Save(screenshot, $"/Users/marcos/Desktop/screenshot-{i}"); | |
//#endif | |
// } | |
//} | |
#if DEBUG | |
private static void Save(CGImage screenshot, string filename) | |
{ | |
var imageFormat = UTType.PNG; | |
var fileURL = new NSUrl($"{filename}.{imageFormat.ToString().ToLowerInvariant()}", false); | |
using (var dataConsumer = new CGDataConsumer(fileURL)) | |
{ | |
var imageDestination = CGImageDestination.Create(dataConsumer, imageFormat, 1); | |
imageDestination.AddImage(screenshot); | |
imageDestination.Close(); | |
} | |
} | |
#endif | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment