[gimp] plug-ins: implementation of the Freedesktop portal for screenshot.



commit 53a03b38e5860afe616e91d82cf9fed179be0fb3
Author: Jehan <jehan girinstud io>
Date:   Sat Dec 16 02:15:57 2017 +0100

    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

 plug-ins/screenshot/Makefile.am              |    2 +
 plug-ins/screenshot/screenshot-freedesktop.c |  199 ++++++++++++++++++++++++++
 plug-ins/screenshot/screenshot-freedesktop.h |   32 ++++
 plug-ins/screenshot/screenshot.c             |   10 ++-
 plug-ins/screenshot/screenshot.h             |    1 +
 5 files changed, 243 insertions(+), 1 deletions(-)
---
diff --git a/plug-ins/screenshot/Makefile.am b/plug-ins/screenshot/Makefile.am
index daf3364..debb488 100644
--- a/plug-ins/screenshot/Makefile.am
+++ b/plug-ins/screenshot/Makefile.am
@@ -46,6 +46,8 @@ EXTRA_PROGRAMS = screenshot
 screenshot_SOURCES = \
        screenshot.c                    \
        screenshot.h                    \
+       screenshot-freedesktop.c        \
+       screenshot-freedesktop.h        \
        screenshot-gnome-shell.c        \
        screenshot-gnome-shell.h        \
        screenshot-icon.h               \
diff --git a/plug-ins/screenshot/screenshot-freedesktop.c b/plug-ins/screenshot/screenshot-freedesktop.c
new file mode 100644
index 0000000..1a55596
--- /dev/null
+++ b/plug-ins/screenshot/screenshot-freedesktop.c
@@ -0,0 +1,199 @@
+/* GIMP - The GNU Image Manipulation Program
+ * 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 2016      Michael Natterer <mitch gimp org>
+ * Copyright 2017      Jehan <jehan 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "screenshot.h"
+#include "screenshot-freedesktop.h"
+
+
+static GDBusProxy *proxy = NULL;
+
+gboolean
+screenshot_freedesktop_available (void)
+{
+  proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                         G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                         NULL,
+                                         "org.freedesktop.portal.Desktop",
+                                         "/org/freedesktop/portal/desktop",
+                                         "org.freedesktop.portal.Screenshot",
+                                         NULL, NULL);
+
+  if (proxy)
+    {
+      GError *error = NULL;
+
+      g_dbus_proxy_call_sync (proxy, "org.freedesktop.DBus.Peer.Ping",
+                              NULL,
+                              G_DBUS_CALL_FLAGS_NONE,
+                              -1, NULL, &error);
+      if (! error)
+        return TRUE;
+
+      g_clear_error (&error);
+
+      g_object_unref (proxy);
+      proxy = NULL;
+    }
+
+  return FALSE;
+}
+
+ScreenshotCapabilities
+screenshot_freedesktop_get_capabilities (void)
+{
+  /* Portal has no capabilities other than root screenshot! */
+  return 0;
+}
+
+static void
+screenshot_freedesktop_dbus_signal (GDBusProxy *proxy,
+                                    gchar      *sender_name,
+                                    gchar      *signal_name,
+                                    GVariant   *parameters,
+                                    gint32     *image_ID)
+{
+  if (g_strcmp0 (signal_name, "Response") == 0)
+    {
+      GVariant *results;
+      guint32   response;
+
+      g_variant_get (parameters, "(u@a{sv})",
+                     &response,
+                     &results);
+
+      /* Possible values:
+       * 0: Success, the request is carried out
+       * 1: The user cancelled the interaction
+       * 2: The user interaction was ended in some other way
+       * Cf. 
https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.Request.xml
+       */
+      if (response == 0)
+        {
+          gchar *uri;
+
+          if (g_variant_lookup (results, "uri", "s", &uri))
+            {
+              GFile *file = g_file_new_for_uri (uri);
+              gchar *path = g_file_get_path (file);
+
+              *image_ID = gimp_file_load (GIMP_RUN_NONINTERACTIVE,
+                                          path, path);
+              gimp_image_set_filename (*image_ID, "screenshot.png");
+
+              /* Delete the actual file. */
+              g_file_delete (file, NULL, NULL);
+
+              g_object_unref (file);
+              g_free (path);
+              g_free (uri);
+            }
+        }
+
+      g_variant_unref (results);
+      /* Quit anyway. */
+      gtk_main_quit ();
+    }
+}
+
+GimpPDBStatusType
+screenshot_freedesktop_shoot (ScreenshotValues  *shootvals,
+                              GdkScreen         *screen,
+                              gint32            *image_ID,
+                              GError           **error)
+{
+  GVariant *retval;
+  gchar    *opath = NULL;
+
+  if (shootvals->shoot_type != SHOOT_ROOT)
+    {
+      /* This should not happen. */
+      return GIMP_PDB_EXECUTION_ERROR;
+    }
+
+  if (shootvals->screenshot_delay > 0)
+    screenshot_delay (shootvals->screenshot_delay);
+
+  retval = g_dbus_proxy_call_sync (proxy, "Screenshot",
+                                   g_variant_new ("(sa{sv})", "", NULL),
+                                   G_DBUS_CALL_FLAGS_NONE,
+                                   -1, NULL, error);
+  g_object_unref (proxy);
+  proxy = NULL;
+  if (retval)
+    {
+      g_variant_get (retval, "(o)", &opath);
+      g_variant_unref (retval);
+    }
+
+  if (opath)
+    {
+      GDBusProxy *proxy2 = NULL;
+
+      proxy2 = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                              G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                              NULL,
+                                              "org.freedesktop.portal.Desktop",
+                                              opath,
+                                              "org.freedesktop.portal.Request",
+                                              NULL, NULL);
+      *image_ID = 0;
+      g_signal_connect (proxy2, "g-signal",
+                        G_CALLBACK (screenshot_freedesktop_dbus_signal),
+                        image_ID);
+
+      gtk_main ();
+      g_object_unref (proxy2);
+      g_free (opath);
+
+      /* Signal got a response. */
+      if (*image_ID)
+        {
+          GimpColorProfile *profile;
+
+          /* Just assign profile of current monitor. This will work only
+           * as long as this is a single-display setup.
+           * We need to figure out how to do better color management for
+           * portal screenshots.
+           * TODO!
+           */
+          profile = gimp_screen_get_color_profile (screen,
+                                                   shootvals->monitor);
+          if (profile)
+            {
+              gimp_image_set_color_profile (*image_ID, profile);
+              g_object_unref (profile);
+            }
+
+          return GIMP_PDB_SUCCESS;
+        }
+    }
+
+  return GIMP_PDB_EXECUTION_ERROR;
+}
diff --git a/plug-ins/screenshot/screenshot-freedesktop.h b/plug-ins/screenshot/screenshot-freedesktop.h
new file mode 100644
index 0000000..81e2111
--- /dev/null
+++ b/plug-ins/screenshot/screenshot-freedesktop.h
@@ -0,0 +1,32 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SCREENSHOT_FREEDESKTOP_H__
+#define __SCREENSHOT_FREEDESKTOP_H__
+
+
+gboolean               screenshot_freedesktop_available        (void);
+
+ScreenshotCapabilities screenshot_freedesktop_get_capabilities (void);
+
+GimpPDBStatusType      screenshot_freedesktop_shoot            (ScreenshotValues  *shootvals,
+                                                                GdkScreen         *screen,
+                                                                gint32            *image_ID,
+                                                                GError           **error);
+
+
+#endif /* __SCREENSHOT_FREEDESKTOP_H__ */
diff --git a/plug-ins/screenshot/screenshot.c b/plug-ins/screenshot/screenshot.c
index f54ae44..7fa4a2e 100644
--- a/plug-ins/screenshot/screenshot.c
+++ b/plug-ins/screenshot/screenshot.c
@@ -27,6 +27,7 @@
 #include <libgimp/gimpui.h>
 
 #include "screenshot.h"
+#include "screenshot-freedesktop.h"
 #include "screenshot-gnome-shell.h"
 #include "screenshot-icon.h"
 #include "screenshot-kwin.h"
@@ -219,6 +220,11 @@ run (const gchar      *name,
       capabilities = screenshot_x11_get_capabilities ();
     }
 #endif
+  else if (! backend && screenshot_freedesktop_available ())
+    {
+      backend      = SCREENSHOT_BACKEND_FREEDESKTOP;
+      capabilities = screenshot_freedesktop_get_capabilities ();
+    }
 
   /* how are we running today? */
   switch (run_mode)
@@ -364,7 +370,9 @@ shoot (GdkScreen  *screen,
     return screenshot_win32_shoot (&shootvals, screen, image_ID, error);
 #endif
 
-  if (backend == SCREENSHOT_BACKEND_GNOME_SHELL)
+  if (backend == SCREENSHOT_BACKEND_FREEDESKTOP)
+    return screenshot_freedesktop_shoot (&shootvals, screen, image_ID, error);
+  else if (backend == SCREENSHOT_BACKEND_GNOME_SHELL)
     return screenshot_gnome_shell_shoot (&shootvals, screen, image_ID, error);
   else if (backend == SCREENSHOT_BACKEND_KWIN)
     return screenshot_kwin_shoot (&shootvals, screen, image_ID, error);
diff --git a/plug-ins/screenshot/screenshot.h b/plug-ins/screenshot/screenshot.h
index 57e5ae8..8b8bb5f 100644
--- a/plug-ins/screenshot/screenshot.h
+++ b/plug-ins/screenshot/screenshot.h
@@ -24,6 +24,7 @@ typedef enum
   SCREENSHOT_BACKEND_NONE,
   SCREENSHOT_BACKEND_OSX,
   SCREENSHOT_BACKEND_WIN32,
+  SCREENSHOT_BACKEND_FREEDESKTOP,
   SCREENSHOT_BACKEND_GNOME_SHELL,
   SCREENSHOT_BACKEND_KWIN,
   SCREENSHOT_BACKEND_X11


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]