Использование портала freedesktop для создания снимков экрана с Python - PullRequest
0 голосов
/ 29 мая 2019

Я пытался написать приложение на flatpak на python, которое использует портал freedesktop для создания скриншотов.Я приспосабливаю плагин freedesktop для скриншотов Gimp, который написан на c, и у меня возникают проблемы с доступом к скриншоту после того, как он сделан и предоставлен в мое приложение.Я получаю URI в форме '/ org / freedesktop / portal / desktop / request / 1_326 / t', а в документации портала freedesktop говорится, что uri указывает на файловую систему fuse, смонтированную в run / user / $ UID / doc / иЯ могу подтвердить, что скриншоты сохраняются там.Однако я не могу получить полезный идентификатор для них, чтобы я мог прикрепить их к электронному письму с моим приложением.

Я экспериментировал со всеми методами на портале документов freedesktop Documentsи не имели успеха там.После вызова прокси-сервера dbus, который возвращает uri, сохраненный в переменной opath, реализация Gimp устанавливает другой прокси-сервер dbus, а затем подключает этот прокси к функции обратного вызова: полный файл, из которого я скопировал эти фрагменты, доступен здесь <<a href="https://github.com/GNOME/gimp/blob/master/plug-ins/screenshot/screenshot-freedesktop.c" rel="nofollow noreferrer">https://github.com/GNOME/gimp/blob/master/plug-ins/screenshot/screenshot-freedesktop.c>

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);

И функция screenshot_freedesktop_dbus_signal выглядит следующим образом:

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);
      gtk_main_quit ();
    }
}

Мой код работает так же, как и функция обратного вызова.Я не могу найти питонический эквивалент функции g_signal_connect.Я попытался добавить обратный вызов для инициализации нового прокси, как это

proxy2 = Gio.DBusProxy.new_for_bus(Gio.BusType.SESSION,
                                            Gio.DBusProxyFlags.NONE,
                                            None,
                                            "org.freedesktop.portal.Desktop",
                                            returned_uri[0],
                                            "org.freedesktop.portal.Request",
                                            None,
                                            G_CALLBACK(self.receive_screenshot_signal),
                                            None)

, но моей функции receive_screenshot_signal не передаются никакие значения, а переданные объекты задачи говорят, что они не завершены.

Я не уверен, куда идти дальше, поэтому любой совет или понимание того, как я могу более эффективно использовать библиотеку dbusproxy и / или порталы freedesktop, будут оценены.Спасибо!

1 Ответ

0 голосов
/ 30 мая 2019

Я решил эту проблему, подписавшись на сигнал от шины на пути к дескриптору запроса.

        args = GLib.Variant('(sa{sv})', (filename, {}))
        result = self.proxy.call_sync('Screenshot',
                                      args,
                                      Gio.DBusCallFlags.NONE,
                                      -1,
                                      None)
        request_handle = result.unpack()[0]
        self.bus.signal_subscribe("org.freedesktop.portal.Desktop",
                                  "org.freedesktop.portal.Request",
                                  "Response",
                                  request_handle,
                                  None,
                                  Gio.DBusSignalFlags.NO_MATCH_RULE,
                                  self.receive_screenshot_signal)

Я не смог найти какой-либо конкретной документации по Gio.bus.signal_subscribe, но вот какфункция обратного вызова обрабатывает возврат:

  def receive_screenshot_signal(self,
                                  connection,
                                  sender,
                                  path,
                                  interface,
                                  signal,
                                  params):
        if not isinstance(params, GLib.Variant):
            print("It's not a variant")
            return
        response_code, results = params.unpack()
        # Response code 0 signifies success
        if response_code != 0 or 'uri' not in results:
            print("Error taking screenshot")
            return
        parsed_uri = urlparse(results['uri'])
        assert parsed_uri.scheme == "file"
        self.screenshot = unquote(parsed_uri.path)
...