1// Writes the main display, or with OWNER the first window of the app of that name with
2// its shadow on transparency, to a PNG, for a session reached over ssh, where
3// screencapture exits 0 without writing a file. Wakes a sleeping display first: asleep,
4// it shows its last frame.
5#include <ApplicationServices/ApplicationServices.h>
6#include <CoreServices/CoreServices.h>
7#include <stdio.h>
8#include <string.h>
9#include <unistd.h>
10
11static CGWindowID window_of(const char *owner) {
12 CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
13 CFStringRef name = CFStringCreateWithCString(NULL, owner, kCFStringEncodingUTF8);
14 CGWindowID found = 0;
15 for (CFIndex i = 0; i < CFArrayGetCount(windows) && !found; i++) {
16 CFDictionaryRef window = CFArrayGetValueAtIndex(windows, i);
17 CFStringRef of = CFDictionaryGetValue(window, kCGWindowOwnerName);
18 CFNumberRef layer = CFDictionaryGetValue(window, kCGWindowLayer);
19 int level = -1;
20 if (layer) CFNumberGetValue(layer, kCFNumberIntType, &level);
21 if (of && level == 0 && CFStringCompare(of, name, 0) == kCFCompareEqualTo)
22 CFNumberGetValue(CFDictionaryGetValue(window, kCGWindowNumber), kCFNumberIntType, &found);
23 }
24 CFRelease(name);
25 CFRelease(windows);
26 return found;
27}
28
29int main(int argc, char **argv) {
30 if (argc != 2 && argc != 3) {
31 fprintf(stderr, "usage: screen OUT.png [OWNER]\n");
32 return 2;
33 }
34 UpdateSystemActivity(UsrActivity);
35 sleep(2);
36 CGImageRef image;
37 if (argc == 3) {
38 CGWindowID window = window_of(argv[2]);
39 if (!window) {
40 fprintf(stderr, "screen: no window of %s\n", argv[2]);
41 return 1;
42 }
43 image = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, window,
44 kCGWindowImageDefault);
45 } else {
46 image = CGDisplayCreateImage(CGMainDisplayID());
47 }
48 if (!image) {
49 fprintf(stderr, "screen: no image\n");
50 return 1;
51 }
52 CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)argv[1], strlen(argv[1]), false);
53 CGImageDestinationRef file = CGImageDestinationCreateWithURL(url, CFSTR("public.png"), 1, NULL);
54 CGImageDestinationAddImage(file, image, NULL);
55 int ok = CGImageDestinationFinalize(file);
56 return ok ? 0 : 1;
57}