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