my @objs = qw/Screenshot.o/;
my @cflags;
my @lflags;
+my @lddlflags;
my %seen_incdir;
my %seen_libdir;
my $X11_lib = $^O eq 'cygwin' ? 'X11.dll' : 'X11';
print "Found Win32\n";
}
+if ($^O eq "darwin") {
+ push @objs, "scdarwin.o";
+ push @cflags, "-DSS_DARWIN";
+ push @lddlflags, qw/-framework OpenGL -framework Cocoa/;
+ print "Found OS X\n";
+}
+
unless (@objs > 1) {
die <<DEAD;
OS unsupported: Headers or libraries not found for a supported GUI
You need to install development headers and libraries for your GUI
For Win32: Platform SDK or a substitute
For X11: X11 headers and libraries, eg. the libX11-dev package on Debian
+For OS X: Install Xcode
DEAD
}
$opts{LIBS} = "@lflags" if @lflags;
$opts{INC} .= " @cflags" if @cflags;
+if (@lddlflags) {
+ $opts{LDDLFLAGS} = $Config{lddlflags} . " @lddlflags";
+}
+
# avoid "... isn't numberic in numeric gt ..." warnings for dev versions
my $eu_mm_version = eval $ExtUtils::MakeMaker::VERSION;
if ($eu_mm_version > 6.06) {
$result =
defined &_win32 ? _win32(0, $opts{decor}, $opts{left}, $opts{top},
$opts{right}, $opts{bottom}) :
- defined &_x11 ? _x11($opts{display}, 0, $opts{left}, $opts{top},
+ defined &_darwin ? _darwin($opts{left}, $opts{top},
+ $opts{right}, $opts{bottom}) :
+ defined &_x11 ? _x11($opts{display}, 0, $opts{left}, $opts{top},
$opts{right}, $opts{bottom}) :
die "No drivers enabled\n";
}
--- /dev/null
+/* Darwin support via OpenGL */
+#include "imext.h"
+#include "imss.h"
+#include <ApplicationServices/ApplicationServices.h>
+#include "OpenGL/OpenGL.h"
+#include "OpenGL/gl.h"
+#include "OpenGL/glu.h"
+#include "OpenGL/glext.h"
+
+i_img *
+imss_darwin(i_img_dim left, i_img_dim top, i_img_dim right, i_img_dim bottom) {
+ CGDisplayCount count;
+ CGDisplayErr err;
+ CGRect rect;
+ CGLPixelFormatObj pix;
+ GLint npix;
+ CGLContextObj ctx;
+ i_img *im;
+ CGDirectDisplayID disp;
+ i_img_dim screen_width, screen_height;
+ i_img_dim width, height;
+
+ CGLPixelFormatAttribute pix_attrs[] =
+ {
+ kCGLPFADisplayMask, 0, /* filled in later */
+ kCGLPFAColorSize, 24,
+ kCGLPFAAlphaSize, 0,
+ kCGLPFAFullScreen,
+ 0
+ };
+
+ i_clear_error();
+
+ disp = CGMainDisplayID();
+
+ /* for now, only interested in the first display */
+ rect = CGDisplayBounds(disp);
+ screen_width = rect.size.width;
+ screen_height = rect.size.height;
+
+ /* adjust negative/zero values to window size */
+ if (left < 0)
+ left += screen_width;
+ if (top < 0)
+ top += screen_height;
+ if (right <= 0)
+ right += screen_width;
+ if (bottom <= 0)
+ bottom += screen_height;
+
+ /* clamp */
+ if (left < 0)
+ left = 0;
+ if (right > screen_width)
+ right = screen_width;
+ if (top < 0)
+ top = 0;
+ if (bottom > screen_height)
+ bottom = screen_height;
+
+ /* validate */
+ if (right <= left || bottom <= top) {
+ i_push_error(0, "image would be empty");
+ return NULL;
+ }
+
+ width = right - left;
+ height = bottom - top;
+
+ /* select a pixel format */
+ pix_attrs[1] = CGDisplayIDToOpenGLDisplayMask(disp);
+ err = CGLChoosePixelFormat(pix_attrs, &pix, &npix);
+ if (err) {
+ i_push_errorf(err, "CGLChoosePixelFormat: %d", (int)err);
+ return NULL;
+ }
+ if (!npix) {
+ i_push_error(0, "No pixel format found");
+ return NULL;
+ }
+
+ /* make ourselves a context */
+ err = CGLCreateContext(pix, NULL, &ctx);
+ CGLDestroyPixelFormat(pix);
+ if (err) {
+ i_push_errorf(err, "CGLCreateContext: %d", (int)err);
+ return NULL;
+ }
+
+ err = CGLSetCurrentContext(ctx);
+ if (err) {
+ i_push_errorf(err, "CGLSetCurrentContext: %d", (int)err);
+ return NULL;
+ }
+
+ err = CGLSetFullScreen(ctx);
+ if (err) {
+ i_push_errorf(err, "CGLSetFullScreen: %d", (int)err);
+ return NULL;
+ }
+
+ /* capture */
+ im = i_img_8_new(width, height, 3);
+ if (im) {
+ size_t line_size = width * 4;
+ size_t buf_size = line_size * height;
+ unsigned char *buf = malloc(buf_size);
+ i_img_dim y = height - 1;
+ i_color *bufp = (i_color *)buf; /* hackish */
+
+ /* GL has the vertical axis going from bottom to top, so translate it */
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(left, screen_height - top - height, width, height,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buf);
+
+ /* transfer */
+ while (y >= 0) {
+ i_plin(im, 0, width, y, bufp);
+ bufp += width;
+ --y;
+ }
+
+ free(buf);
+ }
+
+ /* clean up */
+ CGLSetCurrentContext(NULL);
+ CGLDestroyContext(ctx);
+
+ return im;
+}