2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1998-04-20 11:21:31 +08:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2015-11-08 05:21:53 +08:00
|
|
|
* 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
|
2016-04-03 03:44:09 +08:00
|
|
|
* Copyright 2016 Michael Natterer <mitch@gimp.org>
|
2015-11-08 05:21:53 +08:00
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1998-04-20 11:21:31 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1998-04-20 11:21:31 +08:00
|
|
|
* (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
|
2009-01-18 06:28:01 +08:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1998-04-20 11:21:31 +08:00
|
|
|
*/
|
|
|
|
|
2000-01-08 23:23:28 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <libgimp/gimp.h>
|
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
2015-11-08 05:21:53 +08:00
|
|
|
#include "screenshot.h"
|
plug-ins: implementation of the Freedesktop portal for screenshot.
I am told by the GNOME/Flatpak people that this is what we will
ultimately need to implement. Basically this portal is supposed to work
everywhere, in sandboxes (Flatpak, hopefully Snap too?), but also out
of sandboxes, i.e. in GNOME and KDE, whether Wayland or X11. So that
should be the unique API we will have to implement in the end, and every
desktop environment/sandbox will need to implement this API (which is
good!).
Apparently it is not part of default GNOME yet, but has to be installed
separately (on Fedora, package is xdg-desktop-portal-gtk for GNOME and
xdg-desktop-portal-kde for KDE).
Now there are currently many shortcomings, and in particular, the
screenshot API has apparently no advanced features (at all!). No window
snap, no rectangular selection, no delaying, no choice on including
cursor or decoration, nothing! Apparently this is normal that the API
presents no feature, because "the API itself is not meant to specify the
details how the screenshot is obtained. Instead the portal will present
the user a dialog to take a screenshot, and that screenshot will be
given back to the sandboxed app".
This is acceptable behavior, except that currently, the dialog has none
of the basic features so this is a very bad regression. This is why I
test the freedesktop API last, which basically means it will likely
never be actually used. That's on purpose. At least, the code is in and
will be easy to improve later. Of course, when the Freedesktop portal
for screenshot will finally be featureful, it is meant to be tested
first.
See: https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.Screenshot.xml
2017-12-16 09:15:57 +08:00
|
|
|
#include "screenshot-freedesktop.h"
|
2016-03-30 04:06:31 +08:00
|
|
|
#include "screenshot-gnome-shell.h"
|
2016-04-03 03:44:09 +08:00
|
|
|
#include "screenshot-icon.h"
|
2017-12-09 02:17:58 +08:00
|
|
|
#include "screenshot-kwin.h"
|
2016-04-02 21:02:00 +08:00
|
|
|
#include "screenshot-osx.h"
|
2015-11-08 05:21:53 +08:00
|
|
|
#include "screenshot-x11.h"
|
2016-04-02 21:02:00 +08:00
|
|
|
#include "screenshot-win32.h"
|
2003-08-29 04:23:09 +08:00
|
|
|
|
1999-11-23 06:38:02 +08:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2000-05-02 04:22:55 +08:00
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
/* Defines */
|
2016-03-30 04:06:31 +08:00
|
|
|
|
2005-08-16 03:39:02 +08:00
|
|
|
#define PLUG_IN_PROC "plug-in-screenshot"
|
|
|
|
#define PLUG_IN_BINARY "screenshot"
|
2011-04-09 02:31:34 +08:00
|
|
|
#define PLUG_IN_ROLE "gimp-screenshot"
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2003-08-29 04:23:09 +08:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#ifdef GDK_NATIVE_WINDOW_POINTER
|
2003-08-29 07:38:32 +08:00
|
|
|
#if GLIB_SIZEOF_VOID_P != 4
|
2003-08-29 04:23:09 +08:00
|
|
|
#warning window_id does not fit in PDB_INT32
|
|
|
|
#endif
|
|
|
|
#endif
|
1998-04-20 11:21:31 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2016-03-30 05:34:51 +08:00
|
|
|
static void query (void);
|
|
|
|
static void run (const gchar *name,
|
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals);
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2018-04-29 23:27:47 +08:00
|
|
|
static GimpPDBStatusType shoot (GdkMonitor *monitor,
|
2016-04-02 07:28:34 +08:00
|
|
|
gint32 *image_ID,
|
|
|
|
GError **error);
|
2003-08-29 04:23:09 +08:00
|
|
|
|
2018-04-29 23:27:47 +08:00
|
|
|
static gboolean shoot_dialog (GdkMonitor **monitor);
|
2016-03-30 05:34:51 +08:00
|
|
|
static gboolean shoot_quit_timeout (gpointer data);
|
|
|
|
static gboolean shoot_delay_timeout (gpointer data);
|
2000-05-02 04:22:55 +08:00
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
|
|
|
|
/* Global Variables */
|
2015-11-08 05:21:53 +08:00
|
|
|
|
2018-05-08 09:23:04 +08:00
|
|
|
static ScreenshotBackend backend = SCREENSHOT_BACKEND_NONE;
|
|
|
|
static ScreenshotCapabilities capabilities = 0;
|
|
|
|
static GtkWidget *select_delay_grid = NULL;
|
|
|
|
static GtkWidget *shot_delay_grid = NULL;
|
2015-11-08 05:21:53 +08:00
|
|
|
|
2016-03-30 04:06:31 +08:00
|
|
|
static ScreenshotValues shootvals =
|
|
|
|
{
|
2017-12-10 07:28:22 +08:00
|
|
|
SHOOT_WINDOW, /* root window */
|
2016-03-30 04:06:31 +08:00
|
|
|
TRUE, /* include WM decorations */
|
2017-12-10 07:28:22 +08:00
|
|
|
0, /* window ID */
|
|
|
|
0, /* select delay */
|
|
|
|
0, /* screenshot delay */
|
2016-03-30 04:06:31 +08:00
|
|
|
0, /* coords of region dragged out by pointer */
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2017-02-01 04:26:44 +08:00
|
|
|
FALSE, /* show cursor */
|
|
|
|
SCREENSHOT_PROFILE_POLICY_MONITOR
|
2016-03-30 04:06:31 +08:00
|
|
|
};
|
|
|
|
|
2006-05-16 20:26:20 +08:00
|
|
|
const GimpPlugInInfo PLUG_IN_INFO =
|
1998-04-20 11:21:31 +08:00
|
|
|
{
|
2000-05-02 04:22:55 +08:00
|
|
|
NULL, /* init_proc */
|
2008-10-20 14:04:39 +08:00
|
|
|
NULL, /* quit_proc */
|
2000-05-02 04:22:55 +08:00
|
|
|
query, /* query_proc */
|
|
|
|
run /* run_proc */
|
1998-04-20 11:21:31 +08:00
|
|
|
};
|
|
|
|
|
2000-10-30 02:07:07 +08:00
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
/* Functions */
|
|
|
|
|
|
|
|
MAIN ()
|
|
|
|
|
2000-05-02 04:22:55 +08:00
|
|
|
static void
|
|
|
|
query (void)
|
1998-04-20 11:21:31 +08:00
|
|
|
{
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef args[] =
|
2000-05-02 04:22:55 +08:00
|
|
|
{
|
2009-01-20 04:11:36 +08:00
|
|
|
{ GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
|
2005-08-16 03:39:02 +08:00
|
|
|
{ GIMP_PDB_INT32, "root", "Root window { TRUE, FALSE }" },
|
|
|
|
{ GIMP_PDB_INT32, "window-id", "Window id" },
|
|
|
|
{ GIMP_PDB_INT32, "x1", "(optional) Region left x coord" },
|
|
|
|
{ GIMP_PDB_INT32, "y1", "(optional) Region top y coord" },
|
|
|
|
{ GIMP_PDB_INT32, "x2", "(optional) Region right x coord" },
|
|
|
|
{ GIMP_PDB_INT32, "y2", "(optional) Region bottom y coord" }
|
2000-05-02 04:22:55 +08:00
|
|
|
};
|
|
|
|
|
2006-05-16 20:26:20 +08:00
|
|
|
static const GimpParamDef return_vals[] =
|
2000-05-02 04:22:55 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
{ GIMP_PDB_IMAGE, "image", "Output image" }
|
2000-05-02 04:22:55 +08:00
|
|
|
};
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2005-08-16 03:39:02 +08:00
|
|
|
gimp_install_procedure (PLUG_IN_PROC,
|
2008-10-20 14:04:39 +08:00
|
|
|
N_("Create an image from an area of the screen"),
|
2012-11-11 22:50:25 +08:00
|
|
|
"The plug-in takes screenshots of an "
|
2005-06-15 02:12:11 +08:00
|
|
|
"interactively selected window or of the desktop, "
|
|
|
|
"either the whole desktop or an interactively "
|
2005-06-15 02:25:33 +08:00
|
|
|
"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 "
|
2012-10-14 23:03:24 +08:00
|
|
|
"of the region to be grabbed."
|
2016-03-30 05:34:51 +08:00
|
|
|
"On Mac OS X or on gnome-shell, "
|
2017-03-22 00:45:50 +08:00
|
|
|
"when called non-interactively, the plug-in"
|
2012-10-14 23:03:24 +08:00
|
|
|
"only can take screenshots of the entire root window."
|
|
|
|
"Grabbing a window or a region is not supported"
|
2013-01-27 23:52:38 +08:00
|
|
|
"non-interactively. To grab a region or a particular"
|
2012-10-14 23:03:24 +08:00
|
|
|
"window, you need to use the interactive mode."
|
|
|
|
,
|
2008-10-20 14:04:39 +08:00
|
|
|
"Sven Neumann <sven@gimp.org>, "
|
2012-10-14 23:03:24 +08:00
|
|
|
"Henrik Brix Andersen <brix@gimp.org>,"
|
|
|
|
"Simone Karin Lehmann",
|
2008-10-20 14:04:39 +08:00
|
|
|
"1998 - 2008",
|
|
|
|
"v1.1 (2008/04)",
|
2009-05-17 20:01:36 +08:00
|
|
|
N_("_Screenshot..."),
|
2008-10-20 14:04:39 +08:00
|
|
|
NULL,
|
|
|
|
GIMP_PLUGIN,
|
|
|
|
G_N_ELEMENTS (args),
|
2001-12-06 10:28:58 +08:00
|
|
|
G_N_ELEMENTS (return_vals),
|
2008-10-20 14:04:39 +08:00
|
|
|
args, return_vals);
|
2004-05-06 21:51:56 +08:00
|
|
|
|
2008-09-19 20:01:12 +08:00
|
|
|
gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/File/Create/Acquire");
|
2006-06-17 20:21:47 +08:00
|
|
|
gimp_plugin_icon_register (PLUG_IN_PROC, GIMP_ICON_TYPE_INLINE_PIXBUF,
|
|
|
|
screenshot_icon);
|
1998-04-20 11:21:31 +08:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:23:09 +08:00
|
|
|
static void
|
2003-07-02 21:00:16 +08:00
|
|
|
run (const gchar *name,
|
|
|
|
gint nparams,
|
|
|
|
const GimpParam *param,
|
|
|
|
gint *nreturn_vals,
|
|
|
|
GimpParam **return_vals)
|
1998-04-20 11:21:31 +08:00
|
|
|
{
|
2012-11-28 03:58:05 +08:00
|
|
|
static GimpParam values[2];
|
2016-04-02 07:28:34 +08:00
|
|
|
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
2012-11-28 03:58:05 +08:00
|
|
|
GimpRunMode run_mode;
|
2018-04-29 23:27:47 +08:00
|
|
|
GdkMonitor *monitor = NULL;
|
2005-03-23 05:29:04 +08:00
|
|
|
gint32 image_ID;
|
2016-04-02 07:28:34 +08:00
|
|
|
GError *error = NULL;
|
2000-05-02 04:22:55 +08:00
|
|
|
|
2012-11-28 03:58:05 +08:00
|
|
|
INIT_I18N ();
|
|
|
|
gegl_init (NULL, NULL);
|
2000-05-02 04:22:55 +08:00
|
|
|
|
2012-11-28 03:58:05 +08:00
|
|
|
run_mode = param[0].data.d_int32;
|
2005-03-23 05:29:04 +08:00
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
*nreturn_vals = 1;
|
2000-10-30 02:07:07 +08:00
|
|
|
*return_vals = values;
|
2000-05-02 04:22:55 +08:00
|
|
|
|
2012-11-28 03:58:05 +08:00
|
|
|
values[0].type = GIMP_PDB_STATUS;
|
|
|
|
values[0].data.d_status = status;
|
2012-05-08 07:44:13 +08:00
|
|
|
|
2015-11-08 05:21:53 +08:00
|
|
|
#ifdef PLATFORM_OSX
|
2016-03-30 04:06:31 +08:00
|
|
|
if (! backend && screenshot_osx_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_OSX;
|
|
|
|
capabilities = screenshot_osx_get_capabilities ();
|
2016-04-03 03:44:09 +08:00
|
|
|
|
|
|
|
/* on OS X, this just means shoot the shadow, default to nope */
|
|
|
|
shootvals.decorate = FALSE;
|
2016-03-30 04:06:31 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-04-02 21:02:00 +08:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
if (! backend && screenshot_win32_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_WIN32;
|
|
|
|
capabilities = screenshot_win32_get_capabilities ();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-30 04:06:31 +08:00
|
|
|
if (! backend && screenshot_gnome_shell_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_GNOME_SHELL;
|
|
|
|
capabilities = screenshot_gnome_shell_get_capabilities ();
|
|
|
|
}
|
2017-12-09 02:17:58 +08:00
|
|
|
else if (! backend && screenshot_kwin_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_KWIN;
|
|
|
|
capabilities = screenshot_kwin_get_capabilities ();
|
|
|
|
}
|
2016-03-30 04:06:31 +08:00
|
|
|
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
|
|
if (! backend && screenshot_x11_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_X11;
|
|
|
|
capabilities = screenshot_x11_get_capabilities ();
|
|
|
|
}
|
2015-11-08 05:21:53 +08:00
|
|
|
#endif
|
plug-ins: implementation of the Freedesktop portal for screenshot.
I am told by the GNOME/Flatpak people that this is what we will
ultimately need to implement. Basically this portal is supposed to work
everywhere, in sandboxes (Flatpak, hopefully Snap too?), but also out
of sandboxes, i.e. in GNOME and KDE, whether Wayland or X11. So that
should be the unique API we will have to implement in the end, and every
desktop environment/sandbox will need to implement this API (which is
good!).
Apparently it is not part of default GNOME yet, but has to be installed
separately (on Fedora, package is xdg-desktop-portal-gtk for GNOME and
xdg-desktop-portal-kde for KDE).
Now there are currently many shortcomings, and in particular, the
screenshot API has apparently no advanced features (at all!). No window
snap, no rectangular selection, no delaying, no choice on including
cursor or decoration, nothing! Apparently this is normal that the API
presents no feature, because "the API itself is not meant to specify the
details how the screenshot is obtained. Instead the portal will present
the user a dialog to take a screenshot, and that screenshot will be
given back to the sandboxed app".
This is acceptable behavior, except that currently, the dialog has none
of the basic features so this is a very bad regression. This is why I
test the freedesktop API last, which basically means it will likely
never be actually used. That's on purpose. At least, the code is in and
will be easy to improve later. Of course, when the Freedesktop portal
for screenshot will finally be featureful, it is meant to be tested
first.
See: https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.Screenshot.xml
2017-12-16 09:15:57 +08:00
|
|
|
else if (! backend && screenshot_freedesktop_available ())
|
|
|
|
{
|
|
|
|
backend = SCREENSHOT_BACKEND_FREEDESKTOP;
|
|
|
|
capabilities = screenshot_freedesktop_get_capabilities ();
|
|
|
|
}
|
2015-11-08 05:21:53 +08:00
|
|
|
|
2000-05-02 04:22:55 +08:00
|
|
|
/* how are we running today? */
|
1998-04-20 11:21:31 +08:00
|
|
|
switch (run_mode)
|
2000-05-02 04:22:55 +08:00
|
|
|
{
|
2000-08-22 09:26:57 +08:00
|
|
|
case GIMP_RUN_INTERACTIVE:
|
1998-04-20 11:21:31 +08:00
|
|
|
/* Possibly retrieve data from a previous run */
|
2005-08-16 03:39:02 +08:00
|
|
|
gimp_get_data (PLUG_IN_PROC, &shootvals);
|
2003-08-29 04:23:09 +08:00
|
|
|
shootvals.window_id = 0;
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2017-12-17 04:54:49 +08:00
|
|
|
if ((shootvals.shoot_type == SHOOT_WINDOW &&
|
|
|
|
! (capabilities & SCREENSHOT_CAN_SHOOT_WINDOW)) ||
|
|
|
|
(shootvals.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).
|
|
|
|
*/
|
|
|
|
shootvals.shoot_type = SHOOT_ROOT;
|
|
|
|
}
|
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
/* Get information from the dialog */
|
2018-04-29 23:27:47 +08:00
|
|
|
if (! shoot_dialog (&monitor))
|
2008-10-20 14:04:39 +08:00
|
|
|
status = GIMP_PDB_CANCEL;
|
1998-04-20 11:21:31 +08:00
|
|
|
break;
|
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
case GIMP_RUN_NONINTERACTIVE:
|
2005-07-30 22:10:52 +08:00
|
|
|
if (nparams == 3)
|
2008-10-20 14:04:39 +08:00
|
|
|
{
|
2005-07-30 22:10:52 +08:00
|
|
|
gboolean do_root = param[1].data.d_int32;
|
2007-01-31 17:47:06 +08:00
|
|
|
|
|
|
|
shootvals.shoot_type = do_root ? SHOOT_ROOT : SHOOT_WINDOW;
|
2008-10-20 14:04:39 +08:00
|
|
|
shootvals.window_id = param[2].data.d_int32;
|
2003-11-15 11:06:50 +08:00
|
|
|
shootvals.select_delay = 0;
|
2008-10-20 14:04:39 +08:00
|
|
|
}
|
2005-07-30 22:10:52 +08:00
|
|
|
else if (nparams == 7)
|
2008-10-20 14:04:39 +08:00
|
|
|
{
|
|
|
|
shootvals.shoot_type = SHOOT_REGION;
|
|
|
|
shootvals.window_id = param[2].data.d_int32;
|
2005-07-30 22:10:52 +08:00
|
|
|
shootvals.select_delay = 0;
|
|
|
|
shootvals.x1 = param[3].data.d_int32;
|
|
|
|
shootvals.y1 = param[4].data.d_int32;
|
|
|
|
shootvals.x2 = param[5].data.d_int32;
|
|
|
|
shootvals.y2 = param[6].data.d_int32;
|
2008-10-20 14:04:39 +08:00
|
|
|
}
|
2006-06-29 16:23:08 +08:00
|
|
|
else
|
2005-03-23 05:29:04 +08:00
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
|
|
|
}
|
2003-08-29 04:23:09 +08:00
|
|
|
|
2005-03-23 05:29:04 +08:00
|
|
|
if (! gdk_init_check (NULL, NULL))
|
2008-10-20 14:04:39 +08:00
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
2012-10-14 23:03:24 +08:00
|
|
|
|
2016-03-30 04:06:31 +08:00
|
|
|
if (! (capabilities & SCREENSHOT_CAN_PICK_NONINTERACTIVELY))
|
|
|
|
{
|
|
|
|
if (shootvals.shoot_type == SHOOT_WINDOW ||
|
|
|
|
shootvals.shoot_type == SHOOT_REGION)
|
2017-02-01 04:26:44 +08:00
|
|
|
{
|
|
|
|
status = GIMP_PDB_CALLING_ERROR;
|
|
|
|
}
|
2016-03-30 04:06:31 +08:00
|
|
|
}
|
2012-10-14 23:03:24 +08:00
|
|
|
break;
|
2000-05-02 04:22:55 +08:00
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
case GIMP_RUN_WITH_LAST_VALS:
|
1998-04-20 11:21:31 +08:00
|
|
|
/* Possibly retrieve data from a previous run */
|
2005-08-16 03:39:02 +08:00
|
|
|
gimp_get_data (PLUG_IN_PROC, &shootvals);
|
1998-04-20 11:21:31 +08:00
|
|
|
break;
|
2000-05-02 04:22:55 +08:00
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
default:
|
|
|
|
break;
|
2000-05-02 04:22:55 +08:00
|
|
|
}
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2006-06-18 17:44:43 +08:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
|
|
|
{
|
2018-04-29 23:27:47 +08:00
|
|
|
status = shoot (monitor, &image_ID, &error);
|
2000-10-30 02:07:07 +08:00
|
|
|
}
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
if (status == GIMP_PDB_SUCCESS)
|
2000-05-02 04:22:55 +08:00
|
|
|
{
|
2016-06-01 04:29:49 +08:00
|
|
|
gchar *comment = gimp_get_default_comment ();
|
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
if (shootvals.profile_policy == SCREENSHOT_PROFILE_POLICY_SRGB)
|
|
|
|
{
|
|
|
|
GimpColorProfile *srgb_profile = gimp_color_profile_new_rgb_srgb ();
|
|
|
|
|
|
|
|
gimp_image_convert_color_profile (image_ID,
|
|
|
|
srgb_profile,
|
|
|
|
GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
|
|
|
|
TRUE);
|
|
|
|
g_object_unref (srgb_profile);
|
|
|
|
}
|
|
|
|
|
2016-06-01 04:29:49 +08:00
|
|
|
if (comment)
|
|
|
|
{
|
|
|
|
GimpParasite *parasite;
|
|
|
|
|
|
|
|
parasite = gimp_parasite_new ("gimp-comment",
|
|
|
|
GIMP_PARASITE_PERSISTENT,
|
|
|
|
strlen (comment) + 1, comment);
|
|
|
|
|
|
|
|
gimp_image_attach_parasite (image_ID, parasite);
|
|
|
|
gimp_parasite_free (parasite);
|
|
|
|
|
|
|
|
g_free (comment);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_clean_all (image_ID);
|
|
|
|
|
2000-08-22 09:26:57 +08:00
|
|
|
if (run_mode == GIMP_RUN_INTERACTIVE)
|
2008-10-20 14:04:39 +08:00
|
|
|
{
|
|
|
|
/* Store variable states for next run */
|
|
|
|
gimp_set_data (PLUG_IN_PROC, &shootvals, sizeof (ScreenshotValues));
|
2005-03-23 05:29:04 +08:00
|
|
|
|
2008-10-20 14:04:39 +08:00
|
|
|
gimp_display_new (image_ID);
|
2012-05-07 08:18:32 +08:00
|
|
|
|
|
|
|
/* Give some sort of feedback that the shot is done */
|
|
|
|
if (shootvals.select_delay > 0)
|
|
|
|
{
|
2018-04-29 23:27:47 +08:00
|
|
|
gdk_display_beep (gdk_monitor_get_display (monitor));
|
2018-05-08 06:54:02 +08:00
|
|
|
/* flush so the beep makes it to the server */
|
|
|
|
gdk_display_flush (gdk_monitor_get_display (monitor));
|
2012-05-07 08:18:32 +08:00
|
|
|
}
|
2008-10-20 14:04:39 +08:00
|
|
|
}
|
2005-03-23 05:29:04 +08:00
|
|
|
|
2000-05-02 04:22:55 +08:00
|
|
|
*nreturn_vals = 2;
|
2006-06-18 17:44:43 +08:00
|
|
|
|
|
|
|
values[1].type = GIMP_PDB_IMAGE;
|
2000-05-02 04:22:55 +08:00
|
|
|
values[1].data.d_image = image_ID;
|
|
|
|
}
|
2000-10-30 02:07:07 +08:00
|
|
|
|
2016-04-02 07:28:34 +08:00
|
|
|
if (status != GIMP_PDB_SUCCESS && error)
|
|
|
|
{
|
|
|
|
*nreturn_vals = 2;
|
|
|
|
values[1].type = GIMP_PDB_STRING;
|
|
|
|
values[1].data.d_string = error->message;
|
|
|
|
}
|
|
|
|
|
2003-08-29 04:23:09 +08:00
|
|
|
values[0].data.d_status = status;
|
1998-04-20 11:21:31 +08:00
|
|
|
}
|
|
|
|
|
2005-03-23 05:29:04 +08:00
|
|
|
|
2005-06-15 02:25:33 +08:00
|
|
|
/* The main Screenshot function */
|
2003-08-29 04:23:09 +08:00
|
|
|
|
2015-11-08 05:21:53 +08:00
|
|
|
static GimpPDBStatusType
|
2018-04-29 23:27:47 +08:00
|
|
|
shoot (GdkMonitor *monitor,
|
2016-04-02 07:28:34 +08:00
|
|
|
gint32 *image_ID,
|
|
|
|
GError **error)
|
2012-10-14 23:03:24 +08:00
|
|
|
{
|
|
|
|
#ifdef PLATFORM_OSX
|
2016-03-30 04:06:31 +08:00
|
|
|
if (backend == SCREENSHOT_BACKEND_OSX)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_osx_shoot (&shootvals, monitor, image_ID, error);
|
2012-10-14 23:03:24 +08:00
|
|
|
#endif
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2016-04-02 21:02:00 +08:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
if (backend == SCREENSHOT_BACKEND_WIN32)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_win32_shoot (&shootvals, monitor, image_ID, error);
|
2016-04-02 21:02:00 +08:00
|
|
|
#endif
|
|
|
|
|
plug-ins: implementation of the Freedesktop portal for screenshot.
I am told by the GNOME/Flatpak people that this is what we will
ultimately need to implement. Basically this portal is supposed to work
everywhere, in sandboxes (Flatpak, hopefully Snap too?), but also out
of sandboxes, i.e. in GNOME and KDE, whether Wayland or X11. So that
should be the unique API we will have to implement in the end, and every
desktop environment/sandbox will need to implement this API (which is
good!).
Apparently it is not part of default GNOME yet, but has to be installed
separately (on Fedora, package is xdg-desktop-portal-gtk for GNOME and
xdg-desktop-portal-kde for KDE).
Now there are currently many shortcomings, and in particular, the
screenshot API has apparently no advanced features (at all!). No window
snap, no rectangular selection, no delaying, no choice on including
cursor or decoration, nothing! Apparently this is normal that the API
presents no feature, because "the API itself is not meant to specify the
details how the screenshot is obtained. Instead the portal will present
the user a dialog to take a screenshot, and that screenshot will be
given back to the sandboxed app".
This is acceptable behavior, except that currently, the dialog has none
of the basic features so this is a very bad regression. This is why I
test the freedesktop API last, which basically means it will likely
never be actually used. That's on purpose. At least, the code is in and
will be easy to improve later. Of course, when the Freedesktop portal
for screenshot will finally be featureful, it is meant to be tested
first.
See: https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.Screenshot.xml
2017-12-16 09:15:57 +08:00
|
|
|
if (backend == SCREENSHOT_BACKEND_FREEDESKTOP)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_freedesktop_shoot (&shootvals, monitor, image_ID, error);
|
plug-ins: implementation of the Freedesktop portal for screenshot.
I am told by the GNOME/Flatpak people that this is what we will
ultimately need to implement. Basically this portal is supposed to work
everywhere, in sandboxes (Flatpak, hopefully Snap too?), but also out
of sandboxes, i.e. in GNOME and KDE, whether Wayland or X11. So that
should be the unique API we will have to implement in the end, and every
desktop environment/sandbox will need to implement this API (which is
good!).
Apparently it is not part of default GNOME yet, but has to be installed
separately (on Fedora, package is xdg-desktop-portal-gtk for GNOME and
xdg-desktop-portal-kde for KDE).
Now there are currently many shortcomings, and in particular, the
screenshot API has apparently no advanced features (at all!). No window
snap, no rectangular selection, no delaying, no choice on including
cursor or decoration, nothing! Apparently this is normal that the API
presents no feature, because "the API itself is not meant to specify the
details how the screenshot is obtained. Instead the portal will present
the user a dialog to take a screenshot, and that screenshot will be
given back to the sandboxed app".
This is acceptable behavior, except that currently, the dialog has none
of the basic features so this is a very bad regression. This is why I
test the freedesktop API last, which basically means it will likely
never be actually used. That's on purpose. At least, the code is in and
will be easy to improve later. Of course, when the Freedesktop portal
for screenshot will finally be featureful, it is meant to be tested
first.
See: https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.Screenshot.xml
2017-12-16 09:15:57 +08:00
|
|
|
else if (backend == SCREENSHOT_BACKEND_GNOME_SHELL)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_gnome_shell_shoot (&shootvals, monitor, image_ID, error);
|
2017-12-09 02:17:58 +08:00
|
|
|
else if (backend == SCREENSHOT_BACKEND_KWIN)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_kwin_shoot (&shootvals, monitor, image_ID, error);
|
2016-03-30 04:06:31 +08:00
|
|
|
|
2015-11-08 05:21:53 +08:00
|
|
|
#ifdef GDK_WINDOWING_X11
|
2016-03-30 04:06:31 +08:00
|
|
|
if (backend == SCREENSHOT_BACKEND_X11)
|
2018-04-29 23:27:47 +08:00
|
|
|
return screenshot_x11_shoot (&shootvals, monitor, image_ID, error);
|
2015-11-08 05:21:53 +08:00
|
|
|
#endif
|
2012-10-14 23:03:24 +08:00
|
|
|
|
2015-11-08 05:21:53 +08:00
|
|
|
return GIMP_PDB_CALLING_ERROR; /* silence compiler */
|
2012-10-14 23:03:24 +08:00
|
|
|
}
|
2012-10-17 17:53:45 +08:00
|
|
|
|
2012-10-14 23:03:24 +08:00
|
|
|
|
2005-06-15 02:25:33 +08:00
|
|
|
/* Screenshot dialog */
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2007-02-15 22:38:46 +08:00
|
|
|
static void
|
|
|
|
shoot_dialog_add_hint (GtkNotebook *notebook,
|
|
|
|
ShootType type,
|
|
|
|
const gchar *hint)
|
|
|
|
{
|
|
|
|
GtkWidget *label;
|
|
|
|
|
|
|
|
label = g_object_new (GTK_TYPE_LABEL,
|
|
|
|
"label", hint,
|
|
|
|
"wrap", TRUE,
|
|
|
|
"justify", GTK_JUSTIFY_LEFT,
|
|
|
|
"xalign", 0.0,
|
|
|
|
"yalign", 0.0,
|
|
|
|
NULL);
|
|
|
|
gimp_label_set_attributes (GTK_LABEL (label),
|
|
|
|
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
gtk_notebook_insert_page (notebook, label, NULL, type);
|
|
|
|
gtk_widget_show (label);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shoot_radio_button_toggled (GtkWidget *widget,
|
|
|
|
GtkWidget *notebook)
|
|
|
|
{
|
|
|
|
gimp_radio_button_update (widget, &shootvals.shoot_type);
|
|
|
|
|
2018-05-08 09:23:04 +08:00
|
|
|
if (select_delay_grid)
|
2017-12-10 07:28:22 +08:00
|
|
|
{
|
|
|
|
if (shootvals.shoot_type == SHOOT_ROOT ||
|
|
|
|
(shootvals.shoot_type == SHOOT_WINDOW &&
|
|
|
|
! (capabilities & SCREENSHOT_CAN_PICK_WINDOW)))
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_hide (select_delay_grid);
|
2017-12-10 07:28:22 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_show (select_delay_grid);
|
2017-12-10 07:28:22 +08:00
|
|
|
}
|
|
|
|
}
|
2018-05-08 09:23:04 +08:00
|
|
|
if (shot_delay_grid)
|
2017-12-10 08:30:31 +08:00
|
|
|
{
|
|
|
|
if (shootvals.shoot_type == SHOOT_WINDOW &&
|
|
|
|
(capabilities & SCREENSHOT_CAN_PICK_WINDOW) &&
|
|
|
|
! (capabilities & SCREENSHOT_CAN_DELAY_WINDOW_SHOT))
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_hide (shot_delay_grid);
|
2017-12-10 08:30:31 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_show (shot_delay_grid);
|
2017-12-10 08:30:31 +08:00
|
|
|
}
|
|
|
|
}
|
2007-02-15 22:38:46 +08:00
|
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), shootvals.shoot_type);
|
|
|
|
}
|
|
|
|
|
2000-10-30 02:07:07 +08:00
|
|
|
static gboolean
|
2018-04-29 23:27:47 +08:00
|
|
|
shoot_dialog (GdkMonitor **monitor)
|
1998-04-20 11:21:31 +08:00
|
|
|
{
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkWidget *main_vbox;
|
2017-12-10 07:28:22 +08:00
|
|
|
GtkWidget *notebook1;
|
|
|
|
GtkWidget *notebook2;
|
2014-06-23 05:01:31 +08:00
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label;
|
|
|
|
GtkWidget *button;
|
|
|
|
GtkWidget *toggle;
|
|
|
|
GtkWidget *spinner;
|
2018-05-08 09:23:04 +08:00
|
|
|
GtkWidget *grid;
|
2014-06-23 05:01:31 +08:00
|
|
|
GSList *radio_group = NULL;
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
gboolean run;
|
2017-07-18 21:04:09 +08:00
|
|
|
GtkWidget *cursor_toggle = NULL;
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2005-08-16 03:39:02 +08:00
|
|
|
gimp_ui_init (PLUG_IN_BINARY, FALSE);
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2011-04-09 02:31:34 +08:00
|
|
|
dialog = gimp_dialog_new (_("Screenshot"), PLUG_IN_ROLE,
|
2003-11-06 23:27:05 +08:00
|
|
|
NULL, 0,
|
2008-10-20 14:04:39 +08:00
|
|
|
gimp_standard_help_func, PLUG_IN_PROC,
|
2003-09-03 20:44:10 +08:00
|
|
|
|
2017-02-12 23:18:24 +08:00
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("S_nap"), GTK_RESPONSE_OK,
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2008-10-20 14:04:39 +08:00
|
|
|
NULL);
|
2000-01-08 23:23:28 +08:00
|
|
|
|
2018-05-10 23:04:37 +08:00
|
|
|
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
2005-08-16 03:39:02 +08:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
2005-02-09 04:40:33 +08:00
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
|
2009-07-16 00:57:12 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
|
|
main_vbox, FALSE, FALSE, 0);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_widget_show (main_vbox);
|
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
|
2017-12-10 07:28:22 +08:00
|
|
|
/* Create delay hints notebooks early */
|
|
|
|
notebook1 = g_object_new (GTK_TYPE_NOTEBOOK,
|
|
|
|
"show-border", FALSE,
|
|
|
|
"show-tabs", FALSE,
|
|
|
|
NULL);
|
|
|
|
notebook2 = g_object_new (GTK_TYPE_NOTEBOOK,
|
|
|
|
"show-border", FALSE,
|
|
|
|
"show-tabs", FALSE,
|
|
|
|
NULL);
|
2007-02-15 22:38:46 +08:00
|
|
|
|
|
|
|
/* Area */
|
2005-12-17 01:01:44 +08:00
|
|
|
frame = gimp_frame_new (_("Area"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2011-09-30 18:17:53 +08:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
2005-06-15 02:12:11 +08:00
|
|
|
gtk_widget_show (vbox);
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2017-07-18 21:04:09 +08:00
|
|
|
/* Single window */
|
2017-12-17 04:54:49 +08:00
|
|
|
if (capabilities & SCREENSHOT_CAN_SHOOT_WINDOW)
|
2017-07-18 21:04:09 +08:00
|
|
|
{
|
2017-12-17 04:54:49 +08:00
|
|
|
button = gtk_radio_button_new_with_mnemonic (radio_group,
|
|
|
|
_("Take a screenshot of "
|
|
|
|
"a single _window"));
|
|
|
|
radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (button), "gimp-item-data",
|
|
|
|
GINT_TO_POINTER (SHOOT_WINDOW));
|
|
|
|
|
|
|
|
g_signal_connect (button, "toggled",
|
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
|
|
|
notebook1);
|
|
|
|
g_signal_connect (button, "toggled",
|
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
|
|
|
notebook2);
|
|
|
|
|
|
|
|
/* Window decorations */
|
|
|
|
if (capabilities & SCREENSHOT_CAN_SHOOT_DECORATIONS)
|
|
|
|
{
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("Include window _decoration"));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
|
|
|
|
shootvals.decorate);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 24);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
|
|
|
g_signal_connect (toggle, "toggled",
|
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&shootvals.decorate);
|
|
|
|
|
|
|
|
g_object_bind_property (button, "active",
|
|
|
|
toggle, "sensitive",
|
|
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
}
|
|
|
|
/* Mouse pointer */
|
|
|
|
if (capabilities & SCREENSHOT_CAN_SHOOT_POINTER)
|
|
|
|
{
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
cursor_toggle = gtk_check_button_new_with_mnemonic (_("Include _mouse pointer"));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cursor_toggle),
|
|
|
|
shootvals.show_cursor);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), cursor_toggle, TRUE, TRUE, 24);
|
|
|
|
gtk_widget_show (cursor_toggle);
|
|
|
|
|
|
|
|
g_signal_connect (cursor_toggle, "toggled",
|
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&shootvals.show_cursor);
|
|
|
|
|
|
|
|
g_object_bind_property (button, "active",
|
|
|
|
cursor_toggle, "sensitive",
|
|
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
}
|
2017-07-18 21:04:09 +08:00
|
|
|
|
2000-10-30 02:07:07 +08:00
|
|
|
|
2017-12-17 04:54:49 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
|
|
|
shootvals.shoot_type == SHOOT_WINDOW);
|
|
|
|
}
|
2005-12-17 01:01:44 +08:00
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
/* Whole screen */
|
2005-03-24 05:58:28 +08:00
|
|
|
button = gtk_radio_button_new_with_mnemonic (radio_group,
|
2008-10-20 14:04:39 +08:00
|
|
|
_("Take a screenshot of "
|
2005-12-17 01:01:44 +08:00
|
|
|
"the entire _screen"));
|
2005-03-24 05:58:28 +08:00
|
|
|
radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_widget_show (button);
|
2005-03-24 05:58:28 +08:00
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (button), "gimp-item-data",
|
2005-06-15 02:12:11 +08:00
|
|
|
GINT_TO_POINTER (SHOOT_ROOT));
|
2005-03-24 05:58:28 +08:00
|
|
|
|
|
|
|
g_signal_connect (button, "toggled",
|
2007-02-15 22:38:46 +08:00
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
2017-12-10 07:28:22 +08:00
|
|
|
notebook1);
|
|
|
|
g_signal_connect (button, "toggled",
|
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
|
|
|
notebook2);
|
2005-03-24 05:58:28 +08:00
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
/* Mouse pointer */
|
2015-11-08 05:21:53 +08:00
|
|
|
if (capabilities & SCREENSHOT_CAN_SHOOT_POINTER)
|
|
|
|
{
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
|
|
|
toggle = gtk_check_button_new_with_mnemonic (_("Include _mouse pointer"));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
|
|
|
|
shootvals.show_cursor);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 24);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
|
|
|
g_signal_connect (toggle, "toggled",
|
|
|
|
G_CALLBACK (gimp_toggle_button_update),
|
|
|
|
&shootvals.show_cursor);
|
|
|
|
|
2017-07-18 21:04:09 +08:00
|
|
|
if (cursor_toggle)
|
|
|
|
{
|
|
|
|
g_object_bind_property (cursor_toggle, "active",
|
|
|
|
toggle, "active",
|
|
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
}
|
2015-11-08 05:21:53 +08:00
|
|
|
g_object_bind_property (button, "active",
|
|
|
|
toggle, "sensitive",
|
|
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
}
|
2007-10-31 18:34:42 +08:00
|
|
|
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
|
|
|
shootvals.shoot_type == SHOOT_ROOT);
|
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
/* Dragged region */
|
2016-05-28 23:56:14 +08:00
|
|
|
if (capabilities & SCREENSHOT_CAN_SHOOT_REGION)
|
|
|
|
{
|
|
|
|
button = gtk_radio_button_new_with_mnemonic (radio_group,
|
|
|
|
_("Select a _region to grab"));
|
|
|
|
radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
|
|
|
shootvals.shoot_type == SHOOT_REGION);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (button), "gimp-item-data",
|
|
|
|
GINT_TO_POINTER (SHOOT_REGION));
|
|
|
|
|
|
|
|
g_signal_connect (button, "toggled",
|
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
2017-12-10 07:28:22 +08:00
|
|
|
notebook1);
|
|
|
|
g_signal_connect (button, "toggled",
|
|
|
|
G_CALLBACK (shoot_radio_button_toggled),
|
|
|
|
notebook2);
|
2016-05-28 23:56:14 +08:00
|
|
|
}
|
2005-03-24 05:58:28 +08:00
|
|
|
|
2005-12-17 01:01:44 +08:00
|
|
|
frame = gimp_frame_new (_("Delay"));
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
2017-12-10 07:28:22 +08:00
|
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
2005-12-17 01:01:44 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
gtk_widget_show (vbox);
|
|
|
|
|
2017-12-10 07:28:22 +08:00
|
|
|
/* Selection delay */
|
2018-05-08 09:23:04 +08:00
|
|
|
grid = gtk_grid_new ();
|
|
|
|
select_delay_grid = grid;
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
2017-12-10 07:28:22 +08:00
|
|
|
/* Check if this delay must be hidden from start. */
|
|
|
|
if (shootvals.shoot_type == SHOOT_REGION ||
|
|
|
|
(shootvals.shoot_type == SHOOT_WINDOW &&
|
|
|
|
capabilities & SCREENSHOT_CAN_PICK_WINDOW))
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_show (select_delay_grid);
|
2017-12-10 07:28:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
label = gtk_label_new (_("Selection delay: "));
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (label);
|
2004-10-19 20:34:30 +08:00
|
|
|
|
2014-06-23 05:01:31 +08:00
|
|
|
adj = (GtkAdjustment *)
|
|
|
|
gtk_adjustment_new (shootvals.select_delay,
|
|
|
|
0.0, 100.0, 1.0, 5.0, 0.0);
|
|
|
|
spinner = gtk_spin_button_new (adj, 0, 0);
|
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), spinner, 1, 0, 1, 1);
|
2000-10-30 02:07:07 +08:00
|
|
|
gtk_widget_show (spinner);
|
1998-06-05 00:17:59 +08:00
|
|
|
|
2005-07-01 00:03:24 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2003-08-29 04:23:09 +08:00
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
2005-03-25 07:29:12 +08:00
|
|
|
&shootvals.select_delay);
|
2001-12-31 08:21:10 +08:00
|
|
|
|
2017-02-01 04:26:44 +08:00
|
|
|
/* translators: this is the unit label of a spinbutton */
|
2007-02-15 22:38:46 +08:00
|
|
|
label = gtk_label_new (_("seconds"));
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
|
|
|
|
gtk_widget_set_hexpand (label, TRUE);
|
2018-04-29 07:51:36 +08:00
|
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
1998-06-05 00:17:59 +08:00
|
|
|
gtk_widget_show (label);
|
|
|
|
|
2017-12-10 07:28:22 +08:00
|
|
|
/* Selection delay hints */
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), notebook1, 0, 1, 3, 1);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (notebook1);
|
2017-02-01 04:26:44 +08:00
|
|
|
|
2017-12-10 07:28:22 +08:00
|
|
|
/* No selection delay for full-screen. */
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook1), SHOOT_ROOT, "");
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook1), SHOOT_REGION,
|
2017-02-01 04:26:44 +08:00
|
|
|
_("After the delay, drag your mouse to select "
|
|
|
|
"the region for the screenshot."));
|
|
|
|
#ifdef G_OS_WIN32
|
2017-12-10 07:28:22 +08:00
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook1), SHOOT_WINDOW,
|
2017-02-01 04:26:44 +08:00
|
|
|
_("Click in a window to snap it after delay."));
|
|
|
|
#else
|
2017-12-10 07:28:22 +08:00
|
|
|
if (capabilities & SCREENSHOT_CAN_PICK_WINDOW)
|
|
|
|
{
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook1), SHOOT_WINDOW,
|
|
|
|
_("At the end of the delay, click in a window "
|
|
|
|
"to snap it."));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook1), SHOOT_WINDOW, "");
|
|
|
|
}
|
2017-02-01 04:26:44 +08:00
|
|
|
#endif
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook1), shootvals.shoot_type);
|
|
|
|
|
|
|
|
/* Screenshot delay */
|
2018-05-08 09:23:04 +08:00
|
|
|
grid = gtk_grid_new ();
|
|
|
|
shot_delay_grid = grid;
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), grid, FALSE, FALSE, 0);
|
2017-12-10 08:30:31 +08:00
|
|
|
if (shootvals.shoot_type != SHOOT_WINDOW ||
|
|
|
|
! (capabilities & SCREENSHOT_CAN_PICK_WINDOW) ||
|
|
|
|
(capabilities & SCREENSHOT_CAN_DELAY_WINDOW_SHOT))
|
|
|
|
{
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_widget_show (grid);
|
2017-12-10 08:30:31 +08:00
|
|
|
}
|
2017-12-10 07:28:22 +08:00
|
|
|
|
|
|
|
label = gtk_label_new (_("Screenshot delay: "));
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (label);
|
|
|
|
|
|
|
|
adj = (GtkAdjustment *)
|
|
|
|
gtk_adjustment_new (shootvals.screenshot_delay,
|
|
|
|
0.0, 100.0, 1.0, 5.0, 0.0);
|
|
|
|
spinner = gtk_spin_button_new (adj, 0, 0);
|
|
|
|
gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinner), TRUE);
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), spinner, 1, 0, 1, 1);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (spinner);
|
|
|
|
|
|
|
|
g_signal_connect (adj, "value-changed",
|
|
|
|
G_CALLBACK (gimp_int_adjustment_update),
|
|
|
|
&shootvals.screenshot_delay);
|
|
|
|
|
|
|
|
/* translators: this is the unit label of a spinbutton */
|
|
|
|
label = gtk_label_new (_("seconds"));
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1);
|
|
|
|
gtk_widget_set_hexpand (label, TRUE);
|
2018-04-29 07:51:36 +08:00
|
|
|
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (label);
|
|
|
|
|
|
|
|
/* Screenshot delay hints */
|
2018-05-08 09:23:04 +08:00
|
|
|
gtk_grid_attach (GTK_GRID (grid), notebook2, 0, 1, 3, 1);
|
2017-12-10 07:28:22 +08:00
|
|
|
gtk_widget_show (notebook2);
|
|
|
|
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook2), SHOOT_ROOT,
|
|
|
|
_("After the delay, the screenshot is taken."));
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook2), SHOOT_REGION,
|
|
|
|
_("Once the region is selected, it will be "
|
|
|
|
"captured after this delay."));
|
|
|
|
if (capabilities & SCREENSHOT_CAN_PICK_WINDOW)
|
|
|
|
{
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook2), SHOOT_WINDOW,
|
|
|
|
_("Once the window is selected, it will be "
|
|
|
|
"captured after this delay."));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
shoot_dialog_add_hint (GTK_NOTEBOOK (notebook2), SHOOT_WINDOW,
|
|
|
|
_("After the delay, the active window "
|
|
|
|
"will be captured."));
|
|
|
|
}
|
|
|
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook2), shootvals.shoot_type);
|
2017-02-01 04:26:44 +08:00
|
|
|
|
|
|
|
/* Color profile */
|
|
|
|
frame = gimp_int_radio_group_new (TRUE,
|
|
|
|
_("Color Profile"),
|
|
|
|
G_CALLBACK (gimp_radio_button_update),
|
|
|
|
&shootvals.profile_policy,
|
2017-05-31 04:20:15 +08:00
|
|
|
shootvals.profile_policy,
|
2017-02-01 04:26:44 +08:00
|
|
|
|
|
|
|
_("Tag image with _monitor profile"),
|
|
|
|
SCREENSHOT_PROFILE_POLICY_MONITOR,
|
|
|
|
NULL,
|
|
|
|
|
|
|
|
_("Convert image to sR_GB"),
|
|
|
|
SCREENSHOT_PROFILE_POLICY_SRGB,
|
|
|
|
NULL,
|
|
|
|
|
|
|
|
NULL);
|
|
|
|
gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
|
|
|
|
1998-04-20 11:21:31 +08:00
|
|
|
gtk_widget_show (dialog);
|
|
|
|
|
2003-11-12 02:11:56 +08:00
|
|
|
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
|
2003-11-06 23:27:05 +08:00
|
|
|
|
|
|
|
if (run)
|
|
|
|
{
|
|
|
|
/* get the screen on which we are running */
|
2018-04-29 23:27:47 +08:00
|
|
|
*monitor = gimp_widget_get_monitor (dialog);
|
2003-11-06 23:27:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (dialog);
|
|
|
|
|
|
|
|
if (run)
|
2005-12-17 01:01:44 +08:00
|
|
|
{
|
|
|
|
/* 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 ();
|
|
|
|
}
|
1998-04-20 11:21:31 +08:00
|
|
|
|
2003-11-06 23:27:05 +08:00
|
|
|
return run;
|
1998-06-05 00:17:59 +08:00
|
|
|
}
|
|
|
|
|
2005-11-30 16:01:04 +08:00
|
|
|
static gboolean
|
|
|
|
shoot_quit_timeout (gpointer data)
|
|
|
|
{
|
|
|
|
gtk_main_quit ();
|
2015-11-08 05:21:53 +08:00
|
|
|
|
2005-11-30 16:01:04 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
2016-03-30 05:34:51 +08:00
|
|
|
|
|
|
|
|
|
|
|
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_delay (gint seconds)
|
|
|
|
{
|
|
|
|
g_timeout_add (1000, shoot_delay_timeout, &seconds);
|
|
|
|
gtk_main ();
|
|
|
|
}
|