Add a GDK/X11 screenshot to png utility b=414049 r=dbaron a=npotb
authorTed Mielczarek <ted.mielczarek@gmail.com> and Karl Tomlinson <karlt+@karlt.net>
Mon, 23 Aug 2010 12:11:43 +1200
changeset 51226 d926be226157911cf85a137a21ada79542b6fee5
parent 51225 ed7e9896d4cb9646a7de031a604f9aeb059740c6
child 51227 094a1b4d19b1cec4b308aaaae579a1e644e13f7d
push idunknown
push userunknown
push dateunknown
reviewersdbaron, npotb
bugs414049
milestone2.0b5pre
Add a GDK/X11 screenshot to png utility b=414049 r=dbaron a=npotb
config/autoconf.mk.in
config/system-headers
configure.in
js/src/config/system-headers
testing/tools/screenshot/Makefile.in
testing/tools/screenshot/gdk-screenshot.cpp
toolkit/toolkit-makefiles.sh
toolkit/toolkit-tiers.mk
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -308,16 +308,17 @@ PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLA
 PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
 PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
 
 XCFLAGS		= @XCFLAGS@
 XLDFLAGS	= @XLDFLAGS@
 XLIBS		= @XLIBS@
 XEXT_LIBS	= @XEXT_LIBS@
 XCOMPOSITE_LIBS	= @XCOMPOSITE_LIBS@
+XSS_LIBS	= @XSS_LIBS@
 
 WIN_TOP_SRC	= @WIN_TOP_SRC@
 CYGWIN_WRAPPER	= @CYGWIN_WRAPPER@
 AS_PERL         = @AS_PERL@
 CYGDRIVE_MOUNT	= @CYGDRIVE_MOUNT@
 AR		= @AR@
 AR_FLAGS	= @AR_FLAGS@
 AR_EXTRACT	= @AR_EXTRACT@
--- a/config/system-headers
+++ b/config/system-headers
@@ -886,16 +886,17 @@ wx/image.h
 wx/listctrl.h
 wx/log.h
 wx/toolbar.h
 wx/wx.h
 wx/xrc/xmlres.h
 X11/cursorfont.h
 X11/extensions/Print.h
 X11/extensions/shape.h
+X11/extensions/scrnsaver.h
 X11/extensions/XIElib.h
 X11/extensions/XShm.h
 X11/extensions/Xrender.h
 X11/extensions/Xdamage.h
 X11/extensions/Xcomposite.h
 X11/Intrinsic.h
 X11/keysymdef.h
 X11/keysym.h
--- a/configure.in
+++ b/configure.in
@@ -3466,16 +3466,24 @@ else
         $XLIBS $XEXT_LIBS)
     AC_CHECK_HEADER(X11/extensions/XShm.h)
     if test "$ac_cv_header_X11_extensions_XShm_h" = "yes" &&
         test -n "$_HAVE_XSHM_XEXT"; then
         AC_DEFINE(HAVE_XSHM)
     fi
 
     dnl ========================================================
+    dnl = Check for Xss
+    dnl ========================================================
+    AC_CHECK_HEADER(X11/extensions/scrnsaver.h,
+        AC_CHECK_LIB(Xss, XScreenSaverQueryInfo,
+            [XSS_LIBS="-lXss $XEXT_LIBS $XLIBS"
+             AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS))
+
+    dnl ========================================================
     dnl = Check for XIE
     dnl ========================================================
     AC_CHECK_LIB(XIE, XieFloGeometry, [MOZ_XIE_LIBS="-lXIE"],,
         $XLIBS $XEXT_LIBS)
     AC_CHECK_HEADER(X11/extensions/XIElib.h)
 
     if test "$MOZ_XIE_LIBS"; then
 	dnl ====================================================
@@ -3529,16 +3537,17 @@ else
 
 fi # $no_x
 
 AC_SUBST(XCFLAGS)
 AC_SUBST(XLDFLAGS)
 AC_SUBST(XLIBS)
 AC_SUBST(XEXT_LIBS)
 AC_SUBST(XT_LIBS)
+AC_SUBST(XSS_LIBS)
 
 AC_MSG_CHECKING(for ARM SIMD support in compiler)
 AC_TRY_COMPILE([],
                [asm("uqadd8 r1, r1, r2");],
                result="yes", result="no")
 AC_MSG_RESULT("$result")
 if test "$result" = "yes"; then
     AC_DEFINE(HAVE_ARM_SIMD)
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -886,16 +886,17 @@ wx/image.h
 wx/listctrl.h
 wx/log.h
 wx/toolbar.h
 wx/wx.h
 wx/xrc/xmlres.h
 X11/cursorfont.h
 X11/extensions/Print.h
 X11/extensions/shape.h
+X11/extensions/scrnsaver.h
 X11/extensions/XIElib.h
 X11/extensions/XShm.h
 X11/extensions/Xrender.h
 X11/extensions/Xdamage.h
 X11/extensions/Xcomposite.h
 X11/Intrinsic.h
 X11/keysymdef.h
 X11/keysym.h
new file mode 100644
--- /dev/null
+++ b/testing/tools/screenshot/Makefile.in
@@ -0,0 +1,56 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Karl Tomlinson <karlt+@karlt.net>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
+ifdef MOZ_X11
+
+PROGRAM = screentopng
+CPPSRCS = gdk-screenshot.cpp
+LOCAL_INCLUDES = $(MOZ_GTK2_CFLAGS)
+OS_LIBS = $(MOZ_GTK2_LIBS) $(XSS_LIBS)
+
+endif # X11
+endif # GTK2
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/testing/tools/screenshot/gdk-screenshot.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2009, The Mozilla Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Mozilla Foundation nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY The Mozilla Foundation ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL The Mozilla Foundation BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contributors:
+ *   Ted Mielczarek <ted.mielczarek@gmail.com>
+ *   Karl Tomlinson <karlt+@karlt.net>
+ */
+/*
+ * gdk-screenshot.cpp: Write a screenshot of the root window to stdout in .png
+ * format.
+ */
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#ifdef HAVE_LIBXSS
+#include <X11/extensions/scrnsaver.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+
+gboolean save_to_stdout(const gchar *buf, gsize count,
+                        GError **error, gpointer data)
+{
+  size_t written = fwrite(buf, 1, count, stdout);
+  if (written != count) {
+    g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno),
+                "Write to stdout failed: %s", g_strerror(errno));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+int main(int argc, char** argv)
+{
+  gdk_init(&argc, &argv);
+
+#ifdef HAVE_LIBXSS
+  int event_base, error_base;
+  Bool have_xscreensaver =
+    XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base);
+
+  if (!have_xscreensaver) {
+    fprintf(stderr, "No XScreenSaver extension on display\n");
+  } else {
+    XScreenSaverInfo* info = XScreenSaverAllocInfo();
+    if (!info) {
+      fprintf(stderr, "%s: Out of memory\n", argv[0]);
+      return 1;
+    }
+    XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), info);
+
+    const char* state;
+    const char* til_or_since = NULL;
+    switch (info->state) {
+    case ScreenSaverOff:
+      state = "Off";
+      til_or_since = "XScreenSaver will activate after another %lu seconds idle time\n";
+      break;
+    case ScreenSaverOn:
+      state = "On";
+      if (info->til_or_since) {
+        til_or_since = "XScreenSaver idle timer activated %lu seconds ago\n";
+      } else {
+        til_or_since = "XScreenSaver idle activation is disabled\n";
+      }
+      break;
+    case ScreenSaverDisabled:
+      state = "Disabled";
+      break;
+    default:
+      state = "unknown";
+    }
+
+    const char* kind;
+    switch (info->kind) {
+    case ScreenSaverBlanked:
+      kind = "Blanked";
+      break;
+    case ScreenSaverInternal:
+      state = "Internal";
+      break;
+    case ScreenSaverExternal:
+      state = "External";
+      break;
+    default:
+      state = "unknown";
+    }
+
+    fprintf(stderr, "XScreenSaver state: %s\n", state);
+
+    if (til_or_since) {
+      fprintf(stderr, "XScreenSaver kind: %s\n", kind);
+      fprintf(stderr, til_or_since, info->til_or_since / 1000);
+    }
+
+    fprintf(stderr, "User input has been idle for %lu seconds\n", info->idle / 1000);
+
+    XFree(info);
+  }
+#endif
+
+  GdkWindow* window = gdk_get_default_root_window();
+  GdkPixbuf* screenshot = gdk_pixbuf_get_from_drawable(NULL, window, NULL,
+                                                       0, 0, 0, 0,
+                                                       gdk_screen_width(),
+                                                       gdk_screen_height());
+
+  if (!screenshot) {
+    fprintf(stderr, "%s: failed to create screenshot GdkPixbuf\n", argv[0]);
+    return 1;
+  }
+
+  GError* error = NULL;
+  gdk_pixbuf_save_to_callback(screenshot, save_to_stdout, NULL,
+                              "png", NULL, NULL);
+  if (error) {
+    fprintf(stderr, "%s: failed to write screenshot as png: %s\n",
+            argv[0], error->message);
+    return error->code;
+  }
+
+  return 0;
+}
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -933,16 +933,17 @@ if [ "$ENABLE_TESTS" ]; then
     testing/mochitest/static/Makefile
     testing/mochitest/tests/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/MochiKit/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/tests/Makefile
     testing/mochitest/tests/MochiKit-1.4.2/tests/SimpleTest/Makefile
     testing/mochitest/tests/SimpleTest/Makefile
     testing/mochitest/tests/browser/Makefile
+    testing/tools/screenshot/Makefile
     testing/xpcshell/Makefile
     testing/xpcshell/example/Makefile
     toolkit/components/alerts/test/Makefile
     toolkit/components/autocomplete/tests/Makefile
     toolkit/components/commandlines/test/Makefile
     toolkit/components/contentprefs/tests/Makefile
     toolkit/components/downloads/test/Makefile
     toolkit/components/downloads/test/browser/Makefile
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -275,10 +275,11 @@ ifdef MOZ_SERVICES_SYNC
 tier_platform_dirs += services/crypto
 tier_platform_dirs += services/sync
 endif
 
 ifdef ENABLE_TESTS
 tier_platform_dirs += testing/mochitest
 tier_platform_dirs += testing/xpcshell 
 tier_platform_dirs += testing/mozmill
+tier_platform_dirs += testing/tools/screenshot
 endif