[nautilus] nautilus-application: Publish window->location mappings



commit a1751d3d870c6cdc092f893755623c4ff20e1ef3
Author: Philip Langdale <philipl overt org>
Date:   Wed May 16 12:50:02 2018 -0700

    nautilus-application: Publish window->location mappings
    
    This is a reworking of a long standing Ubuntu patch that publishes
    the set of locations open in each Nautilus window. The motivation
    for this change is that a desktop environment providing special
    icons for things like removable devices and the trash can match
    windows to those icons for highlighting purposes.
    
    In the original incarnation, Unity provided these icons. In today's
    world, I'm maintaining a set of patches for dash-to-dock/ubunut-dock
    that provide these icons too.
    
    The original implementation uses Xids to identify windows, but Xids
    aren't a thing in Wayland so this mechanism is a dead end. Instead,
    we can use the 'gtk application window object paths' which are
    published over dbus by GtkApplications, including Nautilus.
    
    Mutter already detects these, and makes them available on MetaWindows.
    
    The original patch added the mapping property to the fileManager1
    interface, and I have left that part as-is, but it's likely not to
    be the right place to put it. fileManager1 is a generic interface
    and a property that assumes a GTK behaviour doesn't seem right.
    
    We could obviously add it to a new interface under org.gnome.Nautilus,
    but this would be Nautilus specific - although there isn't a huge
    scope for other file managers to implement this property, so perhaps
    that's just fine.
    
    dash-to-dock discussion is readable here:
    
    https://github.com/micheleg/dash-to-dock/pull/677

 data/freedesktop-dbus-interfaces.xml |  8 +++++++
 src/nautilus-application.c           | 27 +++++++++++++++++++++
 src/nautilus-freedesktop-dbus.c      | 46 ++++++++++++++++++++++++++++++++++++
 src/nautilus-freedesktop-dbus.h      |  2 ++
 4 files changed, 83 insertions(+)
---
diff --git a/data/freedesktop-dbus-interfaces.xml b/data/freedesktop-dbus-interfaces.xml
index da37ca0e0..d648205cf 100644
--- a/data/freedesktop-dbus-interfaces.xml
+++ b/data/freedesktop-dbus-interfaces.xml
@@ -31,5 +31,13 @@
       <arg type='s' name='StartupId' direction='in'/>
     </method>
     <property name="OpenLocations" type="as" access="read"/>
+    <!--
+      An extension to the official FileManager1 interface that allows Nautilus
+      to publish a mapping of windows to the locations in each window.
+      This can be used by shell extensions like dash-to-dock/ubuntu-dock to
+      associate special dock icons with windows where the icon's location is
+      open.
+      -->
+    <property name="OpenWindowsWithLocations" type="a{sas}" access="read"/>
   </interface>
 </node>
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 9f0542288..cdf034cb3 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -1400,6 +1400,10 @@ update_dbus_opened_locations (NautilusApplication *self)
     gchar **locations_array;
     NautilusWindow *window;
     GFile *location;
+    const gchar *dbus_object_path = NULL;
+
+    g_autoptr (GVariant) windows_to_locations = NULL;
+    GVariantBuilder windows_to_locations_builder;
 
     g_return_if_fail (NAUTILUS_IS_APPLICATION (self));
 
@@ -1412,10 +1416,22 @@ update_dbus_opened_locations (NautilusApplication *self)
         return;
     }
 
+    dbus_object_path = g_application_get_dbus_object_path (G_APPLICATION (self));
+
+    g_return_if_fail (dbus_object_path);
+
+    g_variant_builder_init (&windows_to_locations_builder, G_VARIANT_TYPE ("a{sas}"));
+
     for (l = priv->windows; l != NULL; l = l->next)
     {
+        guint32 id;
+        g_autofree gchar *path = NULL;
+        GVariantBuilder locations_in_window_builder;
+
         window = l->data;
 
+        g_variant_builder_init (&locations_in_window_builder, G_VARIANT_TYPE ("as"));
+
         for (sl = nautilus_window_get_slots (window); sl; sl = sl->next)
         {
             NautilusWindowSlot *slot = sl->data;
@@ -1426,6 +1442,8 @@ update_dbus_opened_locations (NautilusApplication *self)
                 gchar *uri = g_file_get_uri (location);
                 GList *found = g_list_find_custom (locations, uri, (GCompareFunc) g_strcmp0);
 
+                g_variant_builder_add (&locations_in_window_builder, "s", uri);
+
                 if (!found)
                 {
                     locations = g_list_prepend (locations, uri);
@@ -1437,6 +1455,11 @@ update_dbus_opened_locations (NautilusApplication *self)
                 }
             }
         }
+
+        id = gtk_application_window_get_id (GTK_APPLICATION_WINDOW (window));
+        path = g_strdup_printf ("%s/window/%u", dbus_object_path, id);
+        g_variant_builder_add (&windows_to_locations_builder, "{sas}", path, &locations_in_window_builder);
+        g_variant_builder_clear (&locations_in_window_builder);
     }
 
     locations_array = g_new (gchar *, locations_size + 1);
@@ -1452,6 +1475,10 @@ update_dbus_opened_locations (NautilusApplication *self)
     nautilus_freedesktop_dbus_set_open_locations (priv->fdb_manager,
                                                   (const gchar **) locations_array);
 
+    windows_to_locations = g_variant_ref_sink (g_variant_builder_end (&windows_to_locations_builder));
+    nautilus_freedesktop_dbus_set_open_windows_with_locations (priv->fdb_manager,
+                                                               windows_to_locations);
+
     g_free (locations_array);
     g_list_free_full (locations, g_free);
 }
diff --git a/src/nautilus-freedesktop-dbus.c b/src/nautilus-freedesktop-dbus.c
index ac34662e3..9f72f9b6d 100644
--- a/src/nautilus-freedesktop-dbus.c
+++ b/src/nautilus-freedesktop-dbus.c
@@ -42,6 +42,7 @@ struct _NautilusFreedesktopDBus
     NautilusFreedesktopFileManager1 *skeleton;
 
     GStrv pending_open_locations;
+    GVariant *pending_open_windows_with_locations;
 
     gboolean name_lost;
 };
@@ -172,6 +173,15 @@ bus_acquired_cb (GDBusConnection *conn,
 
         nautilus_freedesktop_dbus_set_open_locations (fdb, (const gchar **) locations);
     }
+
+    if (G_UNLIKELY (fdb->pending_open_windows_with_locations != NULL))
+    {
+        g_autoptr (GVariant) locations = NULL;
+
+        locations = g_steal_pointer (&fdb->pending_open_windows_with_locations);
+
+        nautilus_freedesktop_dbus_set_open_windows_with_locations (fdb, locations);
+    }
 }
 
 static void
@@ -225,6 +235,7 @@ nautilus_freedesktop_dbus_finalize (GObject *object)
     fdb = NAUTILUS_FREEDESKTOP_DBUS (object);
 
     g_clear_pointer (&fdb->pending_open_locations, g_strfreev);
+    g_clear_pointer (&fdb->pending_open_windows_with_locations, g_variant_unref);
 }
 
 static void
@@ -249,6 +260,7 @@ nautilus_freedesktop_dbus_init (NautilusFreedesktopDBus *fdb)
                                     NULL);
     fdb->skeleton = NULL;
     fdb->pending_open_locations = NULL;
+    fdb->pending_open_windows_with_locations = NULL;
     fdb->name_lost = FALSE;
 }
 
@@ -275,6 +287,40 @@ nautilus_freedesktop_dbus_set_open_locations (NautilusFreedesktopDBus  *fdb,
     }
 }
 
+/**
+ * nautilus_freedesktop_dbus_set_open_windows_with_locations:
+ * fdb: The skeleton for the dbus interface
+ * locations: Mapping of windows to locations open in each window
+ *
+ * This allows the application to publish the locations that are open in each window.
+ * It is used by shell extensions like dash-to-dock/ubuntu-dock to match special dock
+ * icons to the windows where the icon's location is open. For example, the Trash or
+ * a removable device.
+ */
+void
+nautilus_freedesktop_dbus_set_open_windows_with_locations (NautilusFreedesktopDBus *fdb,
+                                                           GVariant                *locations)
+{
+    g_return_if_fail (NAUTILUS_IS_FREEDESKTOP_DBUS (fdb));
+
+    if (G_UNLIKELY (fdb->skeleton == NULL))
+    {
+        if (G_LIKELY (fdb->name_lost))
+        {
+            return;
+        }
+
+        g_clear_pointer (&fdb->pending_open_windows_with_locations, g_variant_unref);
+
+        fdb->pending_open_windows_with_locations = g_variant_ref (locations);
+    }
+    else
+    {
+        nautilus_freedesktop_file_manager1_set_open_windows_with_locations (fdb->skeleton,
+                                                                            locations);
+    }
+}
+
 /* Tries to own the org.freedesktop.FileManager1 service name */
 NautilusFreedesktopDBus *
 nautilus_freedesktop_dbus_new (void)
diff --git a/src/nautilus-freedesktop-dbus.h b/src/nautilus-freedesktop-dbus.h
index 57dfef718..6c54be6c4 100644
--- a/src/nautilus-freedesktop-dbus.h
+++ b/src/nautilus-freedesktop-dbus.h
@@ -45,3 +45,5 @@ GType nautilus_freedesktop_dbus_get_type (void);
 NautilusFreedesktopDBus * nautilus_freedesktop_dbus_new (void);
 
 void nautilus_freedesktop_dbus_set_open_locations (NautilusFreedesktopDBus *fdb, const gchar **locations);
+
+void nautilus_freedesktop_dbus_set_open_windows_with_locations (NautilusFreedesktopDBus *fdb, GVariant 
*locations);


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