| 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 | |
| 11 | static 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 | |
| 29 | int 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 | } |