[shotwell: 1/2] Replace nautilus-sendto with org.freedesktop.portal.Email Issue: #111
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [shotwell: 1/2] Replace nautilus-sendto with org.freedesktop.portal.Email Issue: #111
- Date: Mon, 21 Feb 2022 19:01:12 +0000 (UTC)
commit f803e7d2a10450f1ad8cf8d2495678eaa786b90a
Author: Niklas Srich <sirniklax gmail com>
Date: Mon Feb 21 16:27:34 2022 +0100
Replace nautilus-sendto with org.freedesktop.portal.Email Issue: #111
meson.build | 1 +
src/DesktopIntegration.vala | 64 +++++++++++++++++++++++-----------------
src/Portal.vala | 71 +++++++++++++++++++++++++++++++++++++++++++++
src/meson.build | 3 +-
vapi/gdk-wayland-3.0.vapi | 10 +++++++
5 files changed, 121 insertions(+), 28 deletions(-)
---
diff --git a/meson.build b/meson.build
index 21634319..b3b7abb6 100644
--- a/meson.build
+++ b/meson.build
@@ -69,6 +69,7 @@ champlain = dependency('champlain-0.12', version: '>= 0.12.16')
champlain_gtk = dependency('champlain-gtk-0.12')
clutter = dependency('clutter-1.0')
clutter_gtk = dependency('clutter-gtk-1.0')
+gdk = [ dependency('gdk-x11-3.0'), dependency('gdk-wayland-3.0') ]
webpdemux = dependency('libwebpdemux')
webp = dependency('libwebp')
diff --git a/src/DesktopIntegration.vala b/src/DesktopIntegration.vala
index 80e8b2ea..124b9a43 100644
--- a/src/DesktopIntegration.vala
+++ b/src/DesktopIntegration.vala
@@ -6,7 +6,6 @@
namespace DesktopIntegration {
-private const string SENDTO_EXEC = "nautilus-sendto";
private const string DESKTOP_SLIDESHOW_XML_FILENAME = "wallpaper.xml";
private int init_count = 0;
@@ -22,8 +21,6 @@ private bool set_screensaver = false;
public void init() {
if (init_count++ != 0)
return;
-
- send_to_installed = Environment.find_program_in_path(SENDTO_EXEC) != null;
}
public void terminate() {
@@ -93,33 +90,46 @@ public bool is_send_to_installed() {
return send_to_installed;
}
-public void files_send_to(File[] files) {
+public async void files_send_to(File[] files) {
if (files.length == 0)
return;
- string[] argv = new string[files.length + 1];
- argv[0] = SENDTO_EXEC;
-
- for (int ctr = 0; ctr < files.length; ctr++)
- argv[ctr + 1] = files[ctr].get_path();
-
- try {
- AppWindow.get_instance().set_busy_cursor();
-
- Pid child_pid;
- Process.spawn_async(
- "/",
- argv,
- null, // environment
- SpawnFlags.SEARCH_PATH,
- null, // child setup
- out child_pid);
-
- AppWindow.get_instance().set_normal_cursor();
- } catch (Error err) {
- AppWindow.get_instance().set_normal_cursor();
- AppWindow.error_message(_("Unable to launch Nautilus Send-To: %s").printf(err.message));
+ var file_names = new StringBuilder();
+ var files_builder = new VariantBuilder (new VariantType ("ah"));
+ var file_descriptors = new UnixFDList ();
+ for (int i=0; i<files.length; i++){
+ var fd = Posix.open (files[i].get_path (), Posix.O_RDONLY | Posix.O_CLOEXEC);
+ if (fd == -1) {
+ warning ("Send to: cannot open file: '%s'", files[i].get_path ());
+ continue;
+ }
+ try {
+ files_builder.add ("h", file_descriptors.append (fd));
+ } catch (Error e) {
+ warning ("Send to: cannot append file %s to file descriptor list: %s",
+ files[i].get_path(), e.message);
+ }
+ file_names.append(files[i].get_basename());
+ if(i<files.length-1){
+ file_names.append(", ");
+ }
+ }
+
+ var options = new HashTable<string, Variant> (str_hash, str_equal);
+ options.insert ("subject", _("Send files per Mail: ") + file_names.str);
+ options.insert ("attachment_fds", files_builder.end());
+ options.insert ("addresses", new Variant ("as", null));
+ AppWindow.get_instance().set_busy_cursor();
+ try{
+ var response = yield Portal.get_instance().compose_email (options, file_descriptors);
+ if (response == null){
+ throw new DBusError.FAILED("Did not get response");
+ }
+ } catch (Error e){
+ AppWindow.error_message(_("Unable to send file %s, %s").printf(
+ file_names.str, e.message));
}
+ AppWindow.get_instance().set_normal_cursor();
}
public void send_to(Gee.Collection<MediaSource> media) {
@@ -150,7 +160,7 @@ public void send_to(Gee.Collection<MediaSource> media) {
private void on_send_to_export_completed(Exporter exporter, bool is_cancelled) {
if (!is_cancelled)
- files_send_to(exporter.get_exported_files());
+ files_send_to.begin(exporter.get_exported_files());
send_to_exporter = null;
}
diff --git a/src/Portal.vala b/src/Portal.vala
new file mode 100644
index 00000000..24a98de9
--- /dev/null
+++ b/src/Portal.vala
@@ -0,0 +1,71 @@
+[DBus (name="org.freedesktop.portal.Email")]
+private interface PortalEmail : DBusProxy {
+ [DBus (name = "version")]
+ public abstract uint version { get; }
+}
+
+public class Portal : GLib.Object {
+ private static Portal portal;
+ public static Portal get_instance () {
+ if (portal == null){
+ portal = new Portal ();
+ }
+ return portal;
+ }
+
+ private const string BUS_NAME = "org.freedesktop.portal.Desktop";
+ private const string OBJECT_PATH = "/org/freedesktop/portal/desktop";
+
+ private GLib.DBusConnection bus;
+
+ public async Variant compose_email (HashTable<string, Variant> options,
+ UnixFDList attachments) throws Error{
+ if (bus == null){
+ bus = yield Bus.get(BusType.SESSION);
+ }
+
+ options.insert ("handle_token", Portal.generate_handle());
+
+ var options_builder = new VariantBuilder (VariantType.VARDICT);
+ options.foreach ((key, val) => {
+ options_builder.add ("{sv}", key, val);
+ });
+
+ PortalEmail? email = yield bus.get_proxy(BUS_NAME, OBJECT_PATH);
+
+ var response = email.call_with_unix_fd_list_sync (
+ "ComposeEmail",
+ new Variant ("(sa{sv})", yield Portal.get_parent_window(), options_builder),
+ DBusCallFlags.NONE,
+ -1,
+ attachments
+ );
+ return response;
+ }
+
+ private static string generate_handle () {
+ return "%s_%i".printf (
+ GLib.Application.get_default ().application_id.replace (".", "_"),
+ Random.int_range (0, int32.MAX)
+ );
+ }
+
+ private static async string get_parent_window () {
+ var window = AppWindow.get_instance().get_window ();
+
+ if (window is Gdk.Wayland.Window) {
+ var handle = "wayland:";
+ ((Gdk.Wayland.Window) window).export_handle ((w, h) => {
+ handle += h;
+ get_parent_window.callback ();
+ });
+ yield;
+ return handle;
+ } else if (window is Gdk.X11.Window) {
+ return "x11:%x".printf ((uint) ((Gdk.X11.Window) window).get_xid ());
+ } else {
+ warning ("Could not get parent window");
+ return "";
+ }
+ }
+}
diff --git a/src/meson.build b/src/meson.build
index 7b7e92a4..8b1ab4b5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -38,7 +38,7 @@ endif
shotwell_deps = [gio, gee, sqlite, gtk, sqlite, posix, gphoto2,
gstreamer_pbu, gio_unix, gudev, gexiv2, gmodule, unity,
libraw, libexif, sw_plugin, webpdemux, webp, version,
- clutter, clutter_gtk, champlain, champlain_gtk]
+ clutter, clutter_gtk, champlain, champlain_gtk, gdk]
subdir('metadata')
subdir('publishing')
@@ -220,6 +220,7 @@ executable(
'MediaPage.vala',
'MediaDataRepresentation.vala',
'DesktopIntegration.vala',
+ 'Portal.vala',
'MediaInterfaces.vala',
'MediaMonitor.vala',
'PhotoMonitor.vala',
diff --git a/vapi/gdk-wayland-3.0.vapi b/vapi/gdk-wayland-3.0.vapi
new file mode 100644
index 00000000..81e0a25b
--- /dev/null
+++ b/vapi/gdk-wayland-3.0.vapi
@@ -0,0 +1,10 @@
+[CCode (cheader_filename = "gdk/gdkwayland.h")]
+namespace Gdk.Wayland {
+ [CCode (type_id = "GDK_TYPE_WAYLAND_WINDOW", type_check_function = "GDK_IS_WAYLAND_WINDOW")]
+ public class Window : Gdk.Window {
+ public bool export_handle (owned WindowExported callback);
+ }
+
+ [CCode (instance_pos = 2.9)]
+ public delegate void WindowExported (Gdk.Window window, string handle);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]