1 /*********************************/
2 /*                               */
3 /*  MacOSX functions             */
4 /*                               */
5 /*********************************/
6 
7 #include <sys/param.h>
8 #include <sys/stat.h>
9 #include "generic/config.h"
10 
11 #ifdef WITH_COCOA
12 #import <ApplicationServices/ApplicationServices.h>
13 
14 extern char *
15 duplicate_string( const char *);
16 
17 static int
get_screen_height(void)18 get_screen_height(void)
19 {
20 #define MAX_DISPLAYS 32
21 	static int screen_height = -1;
22 	uint32_t          display_count = 0;
23 	CGDirectDisplayID displays[MAX_DISPLAYS];
24 
25 	if ( screen_height >= 0 ) return screen_height;
26 
27 	if ( CGGetOnlineDisplayList(MAX_DISPLAYS, displays, &display_count) == kCGErrorSuccess) {
28 		int i;
29 		CGRect extents = CGRectMake(0,0,1,1);
30 		for ( i = 0; i < display_count; i++)
31 			extents = CGRectUnion(extents, CGDisplayBounds(displays[i]));
32 		screen_height = extents.size.height + .5;
33 	} else {
34 		screen_height = 0;
35 	}
36 	return screen_height;
37 }
38 
39 static int grab_mode_native = 0;
40 
41 uint32_t*
prima_cocoa_application_get_bitmap(int x,int y,int xLen,int yLen,int yMax)42 prima_cocoa_application_get_bitmap( int x, int y, int xLen, int yLen, int yMax)
43 {
44 	CGImageRef      cimg       = NULL;
45 	CGColorSpaceRef colorspace = NULL;
46 	CGContextRef    context    = NULL;
47 	uint32_t       *pixels     = NULL;
48 	int screen_height;
49 
50 	if ( !grab_mode_native ) {
51 		screen_height = get_screen_height();
52 		if ( screen_height > 0 ) y += screen_height - yMax;
53 	}
54 
55 	/* prepare source */
56 	CGDisplayHideCursor(kCGDirectMainDisplay);
57 	if (!( cimg = CGWindowListCreateImage(
58 		CGRectMake(x, y, xLen, yLen),
59 		kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageDefault
60 	))) {
61 		CGDisplayShowCursor(kCGDirectMainDisplay);
62 		goto FAIL;
63 	}
64 	CGDisplayShowCursor(kCGDirectMainDisplay);
65 
66 	if ( !( colorspace = CGColorSpaceCreateDeviceRGB()))
67 		goto FAIL;
68 	if ( !( pixels = malloc( xLen * yLen * 4 )))
69 		goto FAIL;
70  	if ( !( context = CGBitmapContextCreate(
71 		pixels, xLen, yLen, 8, xLen * 4, colorspace,
72 		kCGImageAlphaNoneSkipLast)))
73 		goto FAIL;
74 	CGContextDrawImage(context, CGRectMake(0, 0, xLen, yLen), cimg);
75 	CGColorSpaceRelease(colorspace);
76 	CFRelease(cimg);
77 
78 	return pixels;
79 
80 FAIL:
81 	if (pixels)     free(pixels);
82   	if (colorspace) CGColorSpaceRelease(colorspace);
83 	if (cimg)       CFRelease(cimg);
84 	return NULL;
85 }
86 
87 int
prima_cocoa_is_x11_local(void)88 prima_cocoa_is_x11_local(void)
89 {
90 	struct stat s;
91 	char * display_str = getenv("DISPLAY");
92 	if ( !display_str ) return false;
93 	if ((stat( display_str, &s) < 0) || !S_ISSOCK(s.st_mode))  /* not a socket */
94 		return false;
95 	return true;
96 }
97 
98 char *
prima_cocoa_system_action(char * params)99 prima_cocoa_system_action( char * params)
100 {
101 	if ( strncmp( params, "screen_height", strlen("screen_height")) == 0) {
102 		char buf[16];
103 		snprintf( buf, 16, "%d", get_screen_height());
104 		return duplicate_string(buf);
105 	} else if ( strncmp( params, "grab_mode", strlen("grab_mode")) == 0) {
106 		params += strlen("grab_mode");
107 		while ( *params == ' ' ) params++;
108 		if ( !*params )
109 			return duplicate_string( grab_mode_native ? "native" : "emulated" );
110 		if ( strncmp(params, "native", strlen("native")) == 0) {
111 			grab_mode_native = 1;
112 		} else if ( strncmp(params, "emulated", strlen("emulated")) == 0) {
113 			grab_mode_native = 0;
114 		} else {
115 			fprintf(stderr, "bad grab_mode\n");
116 		}
117 		return NULL;
118 	} else if ( strncmp( params, "local_display", strlen("local_display")) == 0) {
119 		return prima_cocoa_is_x11_local() ? duplicate_string("1") : NULL;
120 	} else {
121 		return NULL;
122 	}
123 }
124 #endif
125