668 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			668 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* PIKA - Photo and Image Kooker Application
 | 
						|
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 | 
						|
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 | 
						|
 *
 | 
						|
 * Original copyright, applying to most contents (license remains unchanged): 
 | 
						|
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 | 
						|
 *
 | 
						|
 * Screenshot plug-in
 | 
						|
 * Copyright 1998-2007 Sven Neumann <sven@gimp.org>
 | 
						|
 * Copyright 2003      Henrik Brix Andersen <brix@gimp.org>
 | 
						|
 * Copyright 2012      Simone Karin Lehmann - OS X patches
 | 
						|
 * Copyright 2016      Michael Natterer <mitch@gimp.org>
 | 
						|
 *
 | 
						|
 * This program is free software: you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation; either version 3 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include <libpika/pika.h>
 | 
						|
#include <libpika/pikaui.h>
 | 
						|
 | 
						|
#include "screenshot.h"
 | 
						|
#include "screenshot-freedesktop.h"
 | 
						|
#include "screenshot-osx.h"
 | 
						|
#include "screenshot-x11.h"
 | 
						|
#include "screenshot-win32.h"
 | 
						|
 | 
						|
#include "libpika/stdplugins-intl.h"
 | 
						|
 | 
						|
 | 
						|
/* Defines */
 | 
						|
 | 
						|
#define PLUG_IN_PROC   "plug-in-screenshot"
 | 
						|
#define PLUG_IN_BINARY "screenshot"
 | 
						|
#define PLUG_IN_ROLE   "pika-screenshot"
 | 
						|
 | 
						|
typedef struct _Screenshot      Screenshot;
 | 
						|
typedef struct _ScreenshotClass ScreenshotClass;
 | 
						|
 | 
						|
struct _Screenshot
 | 
						|
{
 | 
						|
  PikaPlugIn      parent_instance;
 | 
						|
};
 | 
						|
 | 
						|
struct _ScreenshotClass
 | 
						|
{
 | 
						|
  PikaPlugInClass parent_class;
 | 
						|
};
 | 
						|
 | 
						|
#define SCREENSHOT_TYPE  (screenshot_get_type ())
 | 
						|
#define SCREENSHOT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SCREENSHOT_TYPE, Screenshot))
 | 
						|
 | 
						|
GType                   screenshot_get_type         (void) G_GNUC_CONST;
 | 
						|
 | 
						|
static GList          * screenshot_query_procedures (PikaPlugIn           *plug_in);
 | 
						|
static PikaProcedure  * screenshot_create_procedure (PikaPlugIn           *plug_in,
 | 
						|
                                                     const gchar          *name);
 | 
						|
 | 
						|
static PikaValueArray * screenshot_run              (PikaProcedure        *procedure,
 | 
						|
                                                     PikaProcedureConfig  *config,
 | 
						|
                                                     gpointer              run_data);
 | 
						|
 | 
						|
static PikaPDBStatusType   shoot               (GdkMonitor           *monitor,
 | 
						|
                                                PikaImage           **image,
 | 
						|
                                                PikaProcedureConfig  *config,
 | 
						|
                                                GError              **error);
 | 
						|
 | 
						|
static gboolean            shoot_dialog        (PikaProcedure        *procedure,
 | 
						|
                                                PikaProcedureConfig  *config,
 | 
						|
                                                GdkMonitor          **monitor);
 | 
						|
static gboolean            shoot_quit_timeout  (gpointer              data);
 | 
						|
static gboolean            shoot_delay_timeout (gpointer              data);
 | 
						|
 | 
						|
 | 
						|
G_DEFINE_TYPE (Screenshot, screenshot, PIKA_TYPE_PLUG_IN)
 | 
						|
 | 
						|
PIKA_MAIN (SCREENSHOT_TYPE)
 | 
						|
DEFINE_STD_SET_I18N
 | 
						|
 | 
						|
 | 
						|
static ScreenshotBackend       backend      = SCREENSHOT_BACKEND_NONE;
 | 
						|
static ScreenshotCapabilities  capabilities = 0;
 | 
						|
 | 
						|
static void
 | 
						|
screenshot_class_init (ScreenshotClass *klass)
 | 
						|
{
 | 
						|
  PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
 | 
						|
 | 
						|
  plug_in_class->query_procedures = screenshot_query_procedures;
 | 
						|
  plug_in_class->create_procedure = screenshot_create_procedure;
 | 
						|
  plug_in_class->set_i18n         = STD_SET_I18N;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
screenshot_init (Screenshot *screenshot)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static GList *
 | 
						|
screenshot_query_procedures (PikaPlugIn *plug_in)
 | 
						|
{
 | 
						|
  return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
 | 
						|
}
 | 
						|
 | 
						|
static PikaProcedure *
 | 
						|
screenshot_create_procedure (PikaPlugIn  *plug_in,
 | 
						|
                             const gchar *name)
 | 
						|
{
 | 
						|
  PikaProcedure *procedure = NULL;
 | 
						|
 | 
						|
  if (! strcmp (name, PLUG_IN_PROC))
 | 
						|
    {
 | 
						|
      procedure = pika_procedure_new (plug_in, name,
 | 
						|
                                      PIKA_PDB_PROC_TYPE_PLUGIN,
 | 
						|
                                      screenshot_run, NULL, NULL);
 | 
						|
 | 
						|
      pika_procedure_set_menu_label (procedure, _("_Screenshot..."));
 | 
						|
      pika_procedure_add_menu_path (procedure, "<Image>/File/Create");
 | 
						|
 | 
						|
      pika_procedure_set_documentation
 | 
						|
        (procedure,
 | 
						|
         _("Create an image from an area of the screen"),
 | 
						|
         "The plug-in takes screenshots of an "
 | 
						|
         "interactively selected window or of the desktop, "
 | 
						|
         "either the whole desktop or an interactively "
 | 
						|
         "selected region. When called non-interactively, it "
 | 
						|
         "may grab the root window or use the window-id "
 | 
						|
         "passed as a parameter.  The last four parameters "
 | 
						|
         "are optional and can be used to specify the corners "
 | 
						|
         "of the region to be grabbed."
 | 
						|
         "On Mac OS X, "
 | 
						|
         "when called non-interactively, the plug-in"
 | 
						|
         "only can take screenshots of the entire root window."
 | 
						|
         "Grabbing a window or a region is not supported"
 | 
						|
         "non-interactively. To grab a region or a particular"
 | 
						|
         "window, you need to use the interactive mode.",
 | 
						|
         name);
 | 
						|
 | 
						|
      pika_procedure_set_attribution (procedure,
 | 
						|
                                      "Sven Neumann <sven@gimp.org>, "
 | 
						|
                                      "Henrik Brix Andersen <brix@gimp.org>,"
 | 
						|
                                      "Simone Karin Lehmann",
 | 
						|
                                      "1998 - 2008",
 | 
						|
                                      "v1.1 (2008/04)");
 | 
						|
 | 
						|
      pika_procedure_set_icon_pixbuf (procedure,
 | 
						|
                                      gdk_pixbuf_new_from_resource ("/technology.heckin/screenshot-icons/screenshot-icon.png", NULL));
 | 
						|
 | 
						|
      PIKA_PROC_ARG_ENUM (procedure, "run-mode",
 | 
						|
                          "Run mode",
 | 
						|
                          "The run mode",
 | 
						|
                          PIKA_TYPE_RUN_MODE,
 | 
						|
                          PIKA_RUN_NONINTERACTIVE,
 | 
						|
                          G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_INT (procedure, "shoot-type",
 | 
						|
                         _("Shoot _area"),
 | 
						|
                         "The shoot type { SHOOT-WINDOW (0), SHOOT-ROOT (1), "
 | 
						|
                         "SHOOT-REGION (2) }",
 | 
						|
                         0, 2, SHOOT_WINDOW,
 | 
						|
                         G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_INT (procedure, "x1",
 | 
						|
                         "X1",
 | 
						|
                         "Region left x coord for SHOOT-WINDOW",
 | 
						|
                         G_MININT, G_MAXINT, 0,
 | 
						|
                         G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_INT (procedure, "y1",
 | 
						|
                         "Y1",
 | 
						|
                         "Region top y coord for SHOOT-WINDOW",
 | 
						|
                         G_MININT, G_MAXINT, 0,
 | 
						|
                         G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_INT (procedure, "x2",
 | 
						|
                         "X2",
 | 
						|
                         "Region right x coord for SHOOT-WINDOW",
 | 
						|
                         G_MININT, G_MAXINT, 0,
 | 
						|
                         G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_INT (procedure, "y2",
 | 
						|
                         "Y2",
 | 
						|
                         "Region bottom y coord for SHOOT-WINDOW",
 | 
						|
                         G_MININT, G_MAXINT, 0,
 | 
						|
                         G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_ARG_BOOLEAN (procedure, "include-pointer",
 | 
						|
                             "Include _mouse pointer",
 | 
						|
                             "Your pointing device's cursor will be part of the image",
 | 
						|
                             FALSE,
 | 
						|
                             G_PARAM_READWRITE);
 | 
						|
 | 
						|
      /* Since no backends allow window screenshot non-interactively so far, no
 | 
						|
       * need to expose this argument to the API.
 | 
						|
       */
 | 
						|
      PIKA_PROC_AUX_ARG_BOOLEAN (procedure, "include-decoration",
 | 
						|
                                 "Include window _decoration",
 | 
						|
                                 "Title bar, window borders and shadow will be part of the image",
 | 
						|
#ifdef PLATFORM_OSX
 | 
						|
                                 /* on OS X, this just means shoot the shadow, default to nope */
 | 
						|
                                 FALSE,
 | 
						|
#else
 | 
						|
                                 TRUE,
 | 
						|
#endif
 | 
						|
                                 G_PARAM_READWRITE);
 | 
						|
      PIKA_PROC_AUX_ARG_INT     (procedure, "selection-delay",
 | 
						|
                                 "Selection d_elay",
 | 
						|
                                 "Delay before selection of the window or the region",
 | 
						|
                                 0, 20, 0,
 | 
						|
                                 G_PARAM_READWRITE);
 | 
						|
      PIKA_PROC_AUX_ARG_INT     (procedure, "screenshot-delay",
 | 
						|
                                 "Screenshot dela_y",
 | 
						|
                                 "Delay before snapping the screenshot",
 | 
						|
                                 0, 20, 0,
 | 
						|
                                 G_PARAM_READWRITE);
 | 
						|
      PIKA_PROC_AUX_ARG_INT     (procedure, "color-profile",
 | 
						|
                                 _("Color _Profile"),
 | 
						|
                                 "{ SCREENSHOT_PROFILE_POLICY_MONITOR, (0), "
 | 
						|
                                 "SCREENSHOT_PROFILE_POLICY_MONITOR, (1) } ",
 | 
						|
                                 0, 1, SCREENSHOT_PROFILE_POLICY_MONITOR,
 | 
						|
                                 G_PARAM_READWRITE);
 | 
						|
 | 
						|
      PIKA_PROC_VAL_IMAGE (procedure, "image",
 | 
						|
                           "Image",
 | 
						|
                           "Output image",
 | 
						|
                           FALSE,
 | 
						|
                           G_PARAM_READWRITE);
 | 
						|
    }
 | 
						|
 | 
						|
  return procedure;
 | 
						|
}
 | 
						|
 | 
						|
static PikaValueArray *
 | 
						|
screenshot_run (PikaProcedure        *procedure,
 | 
						|
                PikaProcedureConfig  *config,
 | 
						|
                gpointer              run_data)
 | 
						|
{
 | 
						|
  PikaValueArray    *return_vals;
 | 
						|
  PikaPDBStatusType  status = PIKA_PDB_SUCCESS;
 | 
						|
  PikaRunMode        run_mode;
 | 
						|
  GdkMonitor        *monitor = NULL;
 | 
						|
  PikaImage         *image   = NULL;
 | 
						|
  GError            *error   = NULL;
 | 
						|
 | 
						|
  ShootType               shoot_type;
 | 
						|
  ScreenshotProfilePolicy profile_policy;
 | 
						|
 | 
						|
  gegl_init (NULL, NULL);
 | 
						|
 | 
						|
  g_object_get (config,
 | 
						|
                "run-mode",   &run_mode,
 | 
						|
                "shoot-type", &shoot_type,
 | 
						|
                NULL);
 | 
						|
 | 
						|
  if (! gdk_init_check (NULL, NULL))
 | 
						|
    {
 | 
						|
      g_set_error_literal (&error, PIKA_PLUG_IN_ERROR, 0, _("GDK initialization failed."));
 | 
						|
      return pika_procedure_new_return_values (procedure,
 | 
						|
                                               PIKA_PDB_EXECUTION_ERROR,
 | 
						|
                                               error);
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef PLATFORM_OSX
 | 
						|
  if (! backend && screenshot_osx_available ())
 | 
						|
    {
 | 
						|
      backend      = SCREENSHOT_BACKEND_OSX;
 | 
						|
      capabilities = screenshot_osx_get_capabilities ();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef G_OS_WIN32
 | 
						|
  if (! backend && screenshot_win32_available ())
 | 
						|
    {
 | 
						|
      backend      = SCREENSHOT_BACKEND_WIN32;
 | 
						|
      capabilities = screenshot_win32_get_capabilities ();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef GDK_WINDOWING_X11
 | 
						|
  if (! backend && screenshot_x11_available ())
 | 
						|
    {
 | 
						|
      backend      = SCREENSHOT_BACKEND_X11;
 | 
						|
      capabilities = screenshot_x11_get_capabilities ();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
  if (! backend && screenshot_freedesktop_available ())
 | 
						|
    {
 | 
						|
      backend      = SCREENSHOT_BACKEND_FREEDESKTOP;
 | 
						|
      capabilities = screenshot_freedesktop_get_capabilities ();
 | 
						|
    }
 | 
						|
 | 
						|
  if (backend == SCREENSHOT_BACKEND_NONE)
 | 
						|
    {
 | 
						|
      g_set_error_literal (&error, PIKA_PLUG_IN_ERROR, 0,
 | 
						|
                           _("No screenshot backends available."));
 | 
						|
      return pika_procedure_new_return_values (procedure,
 | 
						|
                                               PIKA_PDB_EXECUTION_ERROR,
 | 
						|
                                               error);
 | 
						|
    }
 | 
						|
  /* how are we running today? */
 | 
						|
  switch (run_mode)
 | 
						|
    {
 | 
						|
    case PIKA_RUN_INTERACTIVE:
 | 
						|
      pika_ui_init (PLUG_IN_BINARY);
 | 
						|
 | 
						|
      /* In interactive mode, coords are always reset. */
 | 
						|
      g_object_set (config,
 | 
						|
                    "x1", 0, "y1", 0,
 | 
						|
                    "x2", 0, "y2", 0,
 | 
						|
                    NULL);
 | 
						|
 | 
						|
      if ((shoot_type == SHOOT_WINDOW &&
 | 
						|
           ! (capabilities & SCREENSHOT_CAN_SHOOT_WINDOW)) ||
 | 
						|
          (shoot_type == SHOOT_REGION &&
 | 
						|
           ! (capabilities & SCREENSHOT_CAN_SHOOT_REGION)))
 | 
						|
        {
 | 
						|
          /* Shoot root is the only type of shoot which is definitely
 | 
						|
           * shared by all screenshot backends (basically just snap the
 | 
						|
           * whole display setup).
 | 
						|
           */
 | 
						|
          g_object_set (config, "shoot-type", SHOOT_ROOT, NULL);
 | 
						|
        }
 | 
						|
 | 
						|
      /* Get information from the dialog. Freedesktop portal comes with
 | 
						|
       * its own dialog.
 | 
						|
       */
 | 
						|
      if (backend != SCREENSHOT_BACKEND_FREEDESKTOP)
 | 
						|
        {
 | 
						|
          if (! shoot_dialog (procedure, config, &monitor))
 | 
						|
            status = PIKA_PDB_CANCEL;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          /* This is ugly but in reality we have no idea on which monitor
 | 
						|
           * a screenshot was taken from with portals. It's like a
 | 
						|
           * better-than-nothing trick for easy single-display cases.
 | 
						|
           */
 | 
						|
          monitor = gdk_display_get_monitor (gdk_display_get_default (), 0);
 | 
						|
        }
 | 
						|
      break;
 | 
						|
 | 
						|
    case PIKA_RUN_NONINTERACTIVE:
 | 
						|
      if (backend == SCREENSHOT_BACKEND_FREEDESKTOP)
 | 
						|
        {
 | 
						|
          /* With portals, even the basic full screenshot is interactive. */
 | 
						|
          status = PIKA_PDB_CALLING_ERROR;
 | 
						|
        }
 | 
						|
      else if (! (capabilities & SCREENSHOT_CAN_PICK_NONINTERACTIVELY))
 | 
						|
        {
 | 
						|
          if (shoot_type == SHOOT_WINDOW ||
 | 
						|
              shoot_type == SHOOT_REGION)
 | 
						|
            status = PIKA_PDB_CALLING_ERROR;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
 | 
						|
    case PIKA_RUN_WITH_LAST_VALS:
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  if (status == PIKA_PDB_SUCCESS)
 | 
						|
    status = shoot (monitor, &image, config, &error);
 | 
						|
 | 
						|
  if (status == PIKA_PDB_SUCCESS)
 | 
						|
    {
 | 
						|
      gchar *comment = pika_get_default_comment ();
 | 
						|
 | 
						|
      pika_image_undo_disable (image);
 | 
						|
 | 
						|
      g_object_get (config,
 | 
						|
                    "color-profile", &profile_policy,
 | 
						|
                    NULL);
 | 
						|
 | 
						|
      if (run_mode == PIKA_RUN_NONINTERACTIVE)
 | 
						|
        profile_policy = SCREENSHOT_PROFILE_POLICY_MONITOR;
 | 
						|
 | 
						|
      if (profile_policy == SCREENSHOT_PROFILE_POLICY_SRGB)
 | 
						|
        {
 | 
						|
          PikaColorProfile *srgb_profile = pika_color_profile_new_rgb_srgb ();
 | 
						|
 | 
						|
          pika_image_convert_color_profile (image,
 | 
						|
                                            srgb_profile,
 | 
						|
                                            PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
 | 
						|
                                            TRUE);
 | 
						|
          g_object_unref (srgb_profile);
 | 
						|
        }
 | 
						|
 | 
						|
      if (comment)
 | 
						|
        {
 | 
						|
          PikaParasite *parasite;
 | 
						|
 | 
						|
          parasite = pika_parasite_new ("pika-comment",
 | 
						|
                                        PIKA_PARASITE_PERSISTENT,
 | 
						|
                                        strlen (comment) + 1, comment);
 | 
						|
 | 
						|
          pika_image_attach_parasite (image, parasite);
 | 
						|
          pika_parasite_free (parasite);
 | 
						|
 | 
						|
          g_free (comment);
 | 
						|
        }
 | 
						|
 | 
						|
      pika_image_undo_enable (image);
 | 
						|
 | 
						|
      if (run_mode == PIKA_RUN_INTERACTIVE)
 | 
						|
        {
 | 
						|
          guint select_delay;
 | 
						|
 | 
						|
          pika_display_new (image);
 | 
						|
 | 
						|
          g_object_get (config,
 | 
						|
                        "selection-delay", &select_delay,
 | 
						|
                        NULL);
 | 
						|
          /* Give some sort of feedback that the shot is done */
 | 
						|
          if (select_delay > 0)
 | 
						|
            {
 | 
						|
              gdk_display_beep (gdk_monitor_get_display (monitor));
 | 
						|
              /* flush so the beep makes it to the server */
 | 
						|
              gdk_display_flush (gdk_monitor_get_display (monitor));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
  return_vals = pika_procedure_new_return_values (procedure, status, error);
 | 
						|
 | 
						|
  if (status == PIKA_PDB_SUCCESS)
 | 
						|
    PIKA_VALUES_SET_IMAGE (return_vals, 1, image);
 | 
						|
 | 
						|
  return return_vals;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* The main Screenshot function */
 | 
						|
 | 
						|
static PikaPDBStatusType
 | 
						|
shoot (GdkMonitor           *monitor,
 | 
						|
       PikaImage           **image,
 | 
						|
       PikaProcedureConfig  *config,
 | 
						|
       GError              **error)
 | 
						|
{
 | 
						|
  ShootType shoot_type;
 | 
						|
  gboolean  decorate;
 | 
						|
  guint     select_delay;
 | 
						|
  guint     screenshot_delay;
 | 
						|
  gboolean  show_cursor;
 | 
						|
 | 
						|
  g_object_get (config,
 | 
						|
                "shoot-type",         &shoot_type,
 | 
						|
                "screenshot-delay",   &screenshot_delay,
 | 
						|
                "selection-delay",    &select_delay,
 | 
						|
                "include-decoration", &decorate,
 | 
						|
                "include-pointer",    &show_cursor,
 | 
						|
                NULL);
 | 
						|
 | 
						|
#ifdef PLATFORM_OSX
 | 
						|
  if (backend == SCREENSHOT_BACKEND_OSX)
 | 
						|
    return screenshot_osx_shoot (shoot_type,
 | 
						|
                                 select_delay, screenshot_delay,
 | 
						|
                                 decorate, show_cursor,
 | 
						|
                                 image, error);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef G_OS_WIN32
 | 
						|
  if (backend == SCREENSHOT_BACKEND_WIN32)
 | 
						|
    return screenshot_win32_shoot (shoot_type, screenshot_delay, show_cursor,
 | 
						|
                                   monitor, image, error);
 | 
						|
#endif
 | 
						|
 | 
						|
  if (backend == SCREENSHOT_BACKEND_FREEDESKTOP)
 | 
						|
    return screenshot_freedesktop_shoot (monitor, image, error);
 | 
						|
 | 
						|
#ifdef GDK_WINDOWING_X11
 | 
						|
  if (backend == SCREENSHOT_BACKEND_X11)
 | 
						|
    return screenshot_x11_shoot (config, monitor, image, error);
 | 
						|
#endif
 | 
						|
 | 
						|
  return PIKA_PDB_CALLING_ERROR; /* silence compiler */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*  Screenshot dialog  */
 | 
						|
 | 
						|
static gboolean
 | 
						|
shoot_dialog (PikaProcedure        *procedure,
 | 
						|
              PikaProcedureConfig  *config,
 | 
						|
              GdkMonitor          **monitor)
 | 
						|
{
 | 
						|
  GtkWidget      *dialog;
 | 
						|
  GtkListStore   *store;
 | 
						|
  PikaValueArray *values;
 | 
						|
  GValue          value = G_VALUE_INIT;
 | 
						|
  gboolean        run;
 | 
						|
 | 
						|
  dialog = pika_procedure_dialog_new (procedure,
 | 
						|
                                      PIKA_PROCEDURE_CONFIG (config),
 | 
						|
                                      _("Screenshot"));
 | 
						|
  pika_procedure_dialog_set_ok_label (PIKA_PROCEDURE_DIALOG (dialog), _("S_nap"));
 | 
						|
 | 
						|
  store = pika_int_store_new (_("Take a screenshot of a single window"),   SHOOT_WINDOW,
 | 
						|
                              _("Take a screenshot of the entire screen"), SHOOT_ROOT,
 | 
						|
                              _("Select a region to grab"),                SHOOT_REGION,
 | 
						|
                              NULL);
 | 
						|
  pika_procedure_dialog_get_int_combo (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                       "shoot-type", PIKA_INT_STORE (store));
 | 
						|
 | 
						|
  if (capabilities & SCREENSHOT_CAN_SHOOT_POINTER ||
 | 
						|
      capabilities & SCREENSHOT_CAN_SHOOT_DECORATIONS)
 | 
						|
    {
 | 
						|
      if (! (capabilities & SCREENSHOT_CAN_SHOOT_POINTER))
 | 
						|
        pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                        "contents-box",
 | 
						|
                                        "include-decoration",
 | 
						|
                                        NULL);
 | 
						|
      else if (! (capabilities & SCREENSHOT_CAN_SHOOT_DECORATIONS))
 | 
						|
        pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                        "contents-box",
 | 
						|
                                        "include-pointer",
 | 
						|
                                        NULL);
 | 
						|
      else
 | 
						|
        pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                        "contents-box",
 | 
						|
                                        "include-decoration",
 | 
						|
                                        "include-pointer",
 | 
						|
                                        NULL);
 | 
						|
 | 
						|
      pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                       "contents-frame-title",
 | 
						|
                                       _("Contents"), FALSE, FALSE);
 | 
						|
      pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                        "contents-frame", "contents-frame-title",
 | 
						|
                                        FALSE, "contents-box");
 | 
						|
 | 
						|
      if (capabilities & SCREENSHOT_CAN_SHOOT_DECORATIONS)
 | 
						|
        {
 | 
						|
          values = pika_value_array_new (1);
 | 
						|
          g_value_init (&value, G_TYPE_INT);
 | 
						|
          g_value_set_int (&value, SHOOT_WINDOW);
 | 
						|
          pika_value_array_append (values, &value);
 | 
						|
          g_value_unset (&value);
 | 
						|
          pika_procedure_dialog_set_sensitive_if_in (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                                     "include-decoration",
 | 
						|
                                                     NULL, "shoot-type",
 | 
						|
                                                     values, TRUE);
 | 
						|
        }
 | 
						|
      if (capabilities & SCREENSHOT_CAN_SHOOT_POINTER)
 | 
						|
        {
 | 
						|
          values = pika_value_array_new (1);
 | 
						|
          g_value_init (&value, G_TYPE_INT);
 | 
						|
          g_value_set_int (&value, SHOOT_REGION);
 | 
						|
          pika_value_array_append (values, &value);
 | 
						|
          g_value_unset (&value);
 | 
						|
          pika_procedure_dialog_set_sensitive_if_in (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                                     "include-pointer",
 | 
						|
                                                     NULL, "shoot-type",
 | 
						|
                                                     values, FALSE);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
  if (capabilities & SCREENSHOT_CAN_DELAY_WINDOW_SHOT)
 | 
						|
    {
 | 
						|
      if (capabilities & SCREENSHOT_CAN_PICK_WINDOW)
 | 
						|
        {
 | 
						|
          pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                          "delay-box",
 | 
						|
                                          "selection-delay",
 | 
						|
                                          "screenshot-delay",
 | 
						|
                                          NULL);
 | 
						|
 | 
						|
          values = pika_value_array_new (1);
 | 
						|
          g_value_init (&value, G_TYPE_INT);
 | 
						|
          g_value_set_int (&value, SHOOT_ROOT);
 | 
						|
          pika_value_array_append (values, &value);
 | 
						|
          g_value_unset (&value);
 | 
						|
          pika_procedure_dialog_set_sensitive_if_in (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                                     "selection-delay",
 | 
						|
                                                     NULL, "shoot-type",
 | 
						|
                                                     values, FALSE);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          pika_procedure_dialog_fill_box (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                          "delay-box", "screenshot-delay", NULL);
 | 
						|
        }
 | 
						|
 | 
						|
      pika_procedure_dialog_get_label (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                       "delay-frame-title",
 | 
						|
                                       _("Delay"), FALSE, FALSE);
 | 
						|
      pika_procedure_dialog_fill_frame (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                        "delay-frame", "delay-frame-title",
 | 
						|
                                        FALSE, "delay-box");
 | 
						|
    }
 | 
						|
 | 
						|
  pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), "shoot-type", NULL);
 | 
						|
 | 
						|
  store = pika_int_store_new (_("Tag image with monitor profile"), SCREENSHOT_PROFILE_POLICY_MONITOR,
 | 
						|
                              _("Convert image with sRGB"),        SCREENSHOT_PROFILE_POLICY_SRGB,
 | 
						|
                              NULL);
 | 
						|
  pika_procedure_dialog_get_int_combo (PIKA_PROCEDURE_DIALOG (dialog),
 | 
						|
                                       "color-profile", PIKA_INT_STORE (store));
 | 
						|
 | 
						|
  if ((capabilities & SCREENSHOT_CAN_SHOOT_POINTER) ||
 | 
						|
      (capabilities & SCREENSHOT_CAN_SHOOT_DECORATIONS))
 | 
						|
    pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), "contents-frame", NULL);
 | 
						|
 | 
						|
  if (capabilities & SCREENSHOT_CAN_DELAY_WINDOW_SHOT)
 | 
						|
    pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), "delay-frame", NULL);
 | 
						|
 | 
						|
  pika_procedure_dialog_fill (PIKA_PROCEDURE_DIALOG (dialog), "color-profile", NULL);
 | 
						|
  run = pika_procedure_dialog_run (PIKA_PROCEDURE_DIALOG (dialog));
 | 
						|
 | 
						|
  gtk_widget_destroy (dialog);
 | 
						|
 | 
						|
  if (run)
 | 
						|
    {
 | 
						|
      /*  A short timeout to give the server a chance to
 | 
						|
       *  redraw the area that was obscured by our dialog.
 | 
						|
       */
 | 
						|
      g_timeout_add (100, shoot_quit_timeout, NULL);
 | 
						|
      gtk_main ();
 | 
						|
    }
 | 
						|
 | 
						|
  return run;
 | 
						|
}
 | 
						|
 | 
						|
static gboolean
 | 
						|
shoot_quit_timeout (gpointer data)
 | 
						|
{
 | 
						|
  gtk_main_quit ();
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static gboolean
 | 
						|
shoot_delay_timeout (gpointer data)
 | 
						|
{
 | 
						|
  gint *seconds_left = data;
 | 
						|
 | 
						|
  (*seconds_left)--;
 | 
						|
 | 
						|
  if (!*seconds_left)
 | 
						|
    gtk_main_quit ();
 | 
						|
 | 
						|
  return *seconds_left;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*  public functions  */
 | 
						|
 | 
						|
void
 | 
						|
screenshot_wait_delay (gint seconds)
 | 
						|
{
 | 
						|
  g_timeout_add (1000, shoot_delay_timeout, &seconds);
 | 
						|
  gtk_main ();
 | 
						|
}
 |