From a34b172fbdc926919ffc8c36ddf415b2da913ffa Mon Sep 17 00:00:00 2001
From: c4pp4
Date: Tue, 21 Apr 2026 02:28:35 +0200
Subject: [PATCH 1/1] Add Nemo support and XUbuntuOpenLocationsXids

Based on Impish changes related to OpenWindowsWithLocations
and org.gnome.Nautilus.FileOperations2 (revert).

Signed-off-by: c4pp4
---
 launcher/DeviceLauncherSection.cpp      |   4 +-
 launcher/FileManagerLauncherIcon.cpp    |   2 +-
 launcher/LauncherController.cpp         |   5 +-
 launcher/TrashLauncherIcon.cpp          |   2 +-
 unity-shared/ApplicationManager.h       |   3 -
 unity-shared/BamfApplicationManager.cpp |  25 ------
 unity-shared/BamfApplicationManager.h   |   2 -
 unity-shared/CMakeLists.txt             |   2 -
 unity-shared/FileManager.h              |   5 +-
 unity-shared/GnomeFileManager.cpp       | 108 ++++++++----------------
 unity-shared/GnomeFileManager.h         |   4 +-
 11 files changed, 46 insertions(+), 116 deletions(-)

diff --git a/launcher/DeviceLauncherSection.cpp b/launcher/DeviceLauncherSection.cpp
index 90b1203..bfc922d 100644
--- a/launcher/DeviceLauncherSection.cpp
+++ b/launcher/DeviceLauncherSection.cpp
@@ -22,7 +22,7 @@
 #include "DevicesSettingsImp.h"
 #include "VolumeImp.h"
 #include "VolumeMonitorWrapper.h"
-#include "unity-shared/FileManager.h"
+#include "unity-shared/GnomeFileManager.h"
 
 namespace unity
 {
@@ -34,7 +34,7 @@ DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr c
                                              DeviceNotificationDisplay::Ptr const& notify)
   : monitor_(vm ? vm : std::make_shared<VolumeMonitorWrapper>())
   , devices_settings_(ds ? ds : std::make_shared<DevicesSettingsImp>())
-  , file_manager_(FileManager::GetDefault())
+  , file_manager_(GnomeFileManager::Get())
   , device_notification_display_(notify ? notify : std::make_shared<DeviceNotificationDisplayImp>())
 {
   monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
diff --git a/launcher/FileManagerLauncherIcon.cpp b/launcher/FileManagerLauncherIcon.cpp
index 7e1560a..0926997 100644
--- a/launcher/FileManagerLauncherIcon.cpp
+++ b/launcher/FileManagerLauncherIcon.cpp
@@ -40,7 +40,7 @@ const std::string DEFAULT_ICON = "system-file-manager";
 FileManagerLauncherIcon::FileManagerLauncherIcon(ApplicationPtr const& app, DeviceLauncherSection::Ptr const& dev, FileManager::Ptr const& fm)
   : WindowedLauncherIcon(IconType::APPLICATION)
   , ApplicationLauncherIcon(app)
-  , StorageLauncherIcon(GetIconType(), fm ? fm : FileManager::GetDefault())
+  , StorageLauncherIcon(GetIconType(), fm ? fm : GnomeFileManager::Get())
   , devices_(dev)
 {
   // We disconnect from ApplicationLauncherIcon app signals, as we manage them manually
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index 3a38b5f..2f16a60 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -361,10 +361,7 @@ ApplicationLauncherIcon* Controller::Impl::CreateAppLauncherIcon(ApplicationPtr
 {
   auto const& desktop_file = app->desktop_file();
 
-  if (boost::algorithm::ends_with(desktop_file, "org.gnome.Nautilus.desktop") ||
-      boost::algorithm::ends_with(desktop_file, "nautilus.desktop") ||
-      boost::algorithm::ends_with(desktop_file, "nautilus-folder-handler.desktop") ||
-      boost::algorithm::ends_with(desktop_file, "nautilus-home.desktop"))
+  if (boost::algorithm::ends_with(desktop_file, "nemo.desktop"))
   {
     return new FileManagerLauncherIcon(app, device_section_);
   }
diff --git a/launcher/TrashLauncherIcon.cpp b/launcher/TrashLauncherIcon.cpp
index edf5eea..9c6502e 100644
--- a/launcher/TrashLauncherIcon.cpp
+++ b/launcher/TrashLauncherIcon.cpp
@@ -45,7 +45,7 @@ namespace
 
 TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fm)
   : WindowedLauncherIcon(IconType::TRASH)
-  , StorageLauncherIcon(GetIconType(), fm ? fm : FileManager::GetDefault())
+  , StorageLauncherIcon(GetIconType(), fm ? fm : GnomeFileManager::Get())
   , empty_(true)
 {
   tooltip_text = _("Trash");
diff --git a/unity-shared/ApplicationManager.h b/unity-shared/ApplicationManager.h
index e60a56f..04f6e59 100644
--- a/unity-shared/ApplicationManager.h
+++ b/unity-shared/ApplicationManager.h
@@ -102,8 +102,6 @@ public:
     return !(operator==(other));
   }
 
-  virtual std::string property(std::string const& name) const = 0;
-
   nux::ROProperty<int> monitor;
 
   nux::ROProperty<std::string> title;
@@ -227,7 +225,6 @@ public:
   virtual WindowList GetWindowsForMonitor(int monitor = -1) const = 0;
   virtual ApplicationPtr GetApplicationForWindow(Window xid) const = 0;
   virtual ApplicationWindowPtr GetWindowForId(Window xid) const = 0;
-  virtual ApplicationWindowPtr GetWindowForProperty(const std::string& name, const std::string& value) const = 0;
   virtual void FocusWindowGroup(WindowList const&, bool show_on_visible, int monitor) const = 0;
 
   sigc::signal<void, ApplicationPtr const&> application_started;
diff --git a/unity-shared/BamfApplicationManager.cpp b/unity-shared/BamfApplicationManager.cpp
index fb580ef..b9f56d0 100644
--- a/unity-shared/BamfApplicationManager.cpp
+++ b/unity-shared/BamfApplicationManager.cpp
@@ -209,11 +209,6 @@ Window AppWindow::window_id() const
   return bamf_window_get_xid(bamf_window_);
 }
 
-std::string AppWindow::property(std::string const& property) const
-{
-  return glib::String(bamf_window_get_utf8_prop(bamf_window_, property.c_str())).Str();
-}
-
 WindowType AppWindow::type() const
 {
   switch (bamf_window_get_window_type(bamf_window_))
@@ -730,26 +725,6 @@ ApplicationWindowPtr Manager::GetWindowForId(Window xid) const
   return nullptr;
 }
 
-ApplicationWindowPtr Manager::GetWindowForProperty(std::string const& name, std::string const& value) const
-{
-  if (name.empty())
-    return nullptr;
-
-  for (auto const& win_pair : pool::wins_)
-  {
-    if (win_pair.second->property(name) == value)
-      return win_pair.second;
-  }
-
-  for (auto const& win : GetWindowsForMonitor())
-  {
-    if (win->property(name) == value)
-      return win;
-  }
-
-  return nullptr;
-}
-
 ApplicationList Manager::GetRunningApplications() const
 {
   ApplicationList result;
diff --git a/unity-shared/BamfApplicationManager.h b/unity-shared/BamfApplicationManager.h
index eac6d25..214b383 100644
--- a/unity-shared/BamfApplicationManager.h
+++ b/unity-shared/BamfApplicationManager.h
@@ -81,7 +81,6 @@ public:
 
   WindowType type() const override;
   Window window_id() const override;
-  std::string property(std::string const& name) const override;
   ApplicationPtr application() const override;
   void Quit() const override;
 
@@ -173,7 +172,6 @@ public:
   WindowList GetWindowsForMonitor(int monitor = -1) const override;
   ApplicationPtr GetApplicationForWindow(Window xid) const override;
   ApplicationWindowPtr GetWindowForId(Window xid) const override;
-  ApplicationWindowPtr GetWindowForProperty(const std::string& name, const std::string& value) const override;
 
   ApplicationPtr EnsureApplication(BamfView*) const;
   ApplicationWindowPtr EnsureWindow(BamfView*) const;
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index 673c7dd..b0ac7b1 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -32,7 +32,6 @@ set (UNITY_SHARED_SOURCES
      ExpanderView.cpp
      GnomeFileManager.cpp
      FontSettings.cpp
-     FileManager.cpp
      GraphicsUtils.cpp
      IMTextEntry.cpp
      IconLoader.cpp
@@ -46,7 +45,6 @@ set (UNITY_SHARED_SOURCES
      LayoutSystem.cpp
      LineSeparator.cpp
      MenuManager.cpp
-     NemoFileManager.cpp
      OverlayRenderer.cpp
      OverlayScrollView.cpp
      OverlayWindowButtons.cpp
diff --git a/unity-shared/FileManager.h b/unity-shared/FileManager.h
index 6b802c6..1502c21 100644
--- a/unity-shared/FileManager.h
+++ b/unity-shared/FileManager.h
@@ -45,10 +45,9 @@ public:
 
   virtual void Open(std::string const& uri, uint64_t timestamp = 0) = 0;
   virtual void OpenTrash(uint64_t timestamp) = 0;
-  virtual void CopyFiles(std::set<std::string> const& uris, std::string const& dest,
-                         uint64_t timestamp = 0, Window parent_xid = 0) = 0;
+  virtual void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp = 0) = 0;
   virtual bool TrashFile(std::string const& uri) = 0;
-  virtual void EmptyTrash(uint64_t timestamp = 0, Window parent_xid = 0) = 0;
+  virtual void EmptyTrash(uint64_t timestamp = 0) = 0;
   virtual WindowList WindowsForLocation(std::string const& location) const = 0;
   virtual std::string LocationForWindow(ApplicationWindowPtr const&) const = 0;
 
diff --git a/unity-shared/GnomeFileManager.cpp b/unity-shared/GnomeFileManager.cpp
index bd2a051..a1568f6 100644
--- a/unity-shared/GnomeFileManager.cpp
+++ b/unity-shared/GnomeFileManager.cpp
@@ -32,15 +32,13 @@ namespace unity
 
 namespace
 {
-DECLARE_LOGGER(logger, "unity.filemanager.gnome");
+DECLARE_LOGGER(logger, "unity.filemanager.nemo");
 
 const std::string TRASH_URI = "trash:///";
 const std::string FILE_SCHEMA = "file://";
 
-const std::string NAUTILUS_NAME = "org.gnome.Nautilus";
-const std::string NAUTILUS_FILE_OPS_PATH = "/org/gnome/Nautilus/FileOperations2";
-
-const std::string GTK_WINDOW_PATH_PROPERTY = "_GTK_WINDOW_OBJECT_PATH";
+const std::string NEMO_NAME = "org.Nemo";
+const std::string NEMO_FILE_OPS_PATH = "/org/Nemo";
 }
 
 struct GnomeFileManager::Impl
@@ -49,22 +47,22 @@ struct GnomeFileManager::Impl
     : parent_(parent)
     , filemanager_proxy_("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1", G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS)
   {
-    auto callback = sigc::mem_fun(this, &Impl::OnOpenWindowsWithLocationsChanged);
-    filemanager_proxy_.GetProperty("OpenWindowsWithLocations", callback);
-    filemanager_proxy_.ConnectProperty("OpenWindowsWithLocations", callback);
+    auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsXidsUpdated);
+    filemanager_proxy_.GetProperty("XUbuntuOpenLocationsXids", callback);
+    filemanager_proxy_.ConnectProperty("XUbuntuOpenLocationsXids", callback);
   }
 
-  glib::DBusProxy::Ptr NautilusOperationsProxy() const
+  glib::DBusProxy::Ptr NemoOperationsProxy() const
   {
     auto flags = static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES|G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS);
-    return std::make_shared<glib::DBusProxy>(NAUTILUS_NAME, NAUTILUS_FILE_OPS_PATH,
-                                             "org.gnome.Nautilus.FileOperations2",
+    return std::make_shared<glib::DBusProxy>(NEMO_NAME, NEMO_FILE_OPS_PATH,
+                                             "org.Nemo.FileOperations",
                                              G_BUS_TYPE_SESSION, flags);
   }
 
-  void OnOpenWindowsWithLocationsChanged(GVariant* value)
+  void OnOpenLocationsXidsUpdated(GVariant* value)
   {
-    opened_location_for_window_.clear();
+    opened_location_for_xid_.clear();
 
     if (!value)
     {
@@ -73,7 +71,7 @@ struct GnomeFileManager::Impl
       return;
     }
 
-    if (!g_variant_is_of_type(value, G_VARIANT_TYPE("a{sas}")))
+    if (!g_variant_is_of_type(value, G_VARIANT_TYPE("a{uas}")))
     {
       LOG_ERROR(logger) << "Locations value type is not matching the expected one!";
       parent_->locations_changed.emit();
@@ -82,80 +80,53 @@ struct GnomeFileManager::Impl
 
     GVariantIter iter;
     GVariantIter *str_iter;
-    const char *loc;
-    const char *window_path;
-    std::map<std::string, std::string> opened_locations_for_path;
+    char *loc;
+    guint32 xid;
 
     g_variant_iter_init(&iter, value);
 
-    while (g_variant_iter_loop(&iter, "{&sas}", &window_path, &str_iter))
+    while (g_variant_iter_loop(&iter, "{uas}", &xid, &str_iter))
     {
       while (g_variant_iter_loop(str_iter, "s", &loc))
       {
         /* We only care about the first mentioned location as per our "standard"
          * it's the active one */
-        LOG_DEBUG(logger) << window_path << ": Opened location " << loc;
-        opened_locations_for_path[window_path] = loc;
+        LOG_DEBUG(logger) << xid << ": Opened location " << loc;
+        opened_location_for_xid_[xid] = loc;
+        g_free(loc);
         break;
       }
     }
 
     // We must ensure that we emit the locations_changed signal only when all
     // the parent windows have been registered on the app-manager
-    auto app_manager_not_synced = [this, opened_locations_for_path]
+    auto app_manager_not_synced = [this]
     {
       auto& app_manager = ApplicationManager::Default();
       bool synced = true;
 
-      for (auto const& pair : opened_locations_for_path)
+      for (auto const& pair : opened_location_for_xid_)
       {
-        auto win = app_manager.GetWindowForProperty(GTK_WINDOW_PATH_PROPERTY, pair.first);
-        synced = (win != nullptr);
+        synced = (app_manager.GetWindowForId(pair.first) != nullptr);
 
         if (!synced)
           break;
-
-        LOG_DEBUG(logger) << win->window_id() << ": Opened location " << pair.second;
-        opened_location_for_window_[win] = pair.second;
       }
 
       if (synced)
         parent_->locations_changed.emit();
-      else
-        opened_location_for_window_.clear();
 
       return !synced;
     };
 
     if (app_manager_not_synced())
-      idle_.reset(new glib::Idle(app_manager_not_synced));
-  }
-
-  GVariant *GetPlatformData(uint64_t timestamp, Window parent_xid)
-  {
-    GVariantBuilder builder;
-    char *parent_handle;
-
-    g_variant_builder_init(&builder, G_VARIANT_TYPE ("a{sv}"));
-
-    parent_handle = g_strdup_printf("x11:%lx", parent_xid);
-
-    g_variant_builder_add(&builder, "{sv}", "parent-handle",
-                          g_variant_new_take_string(parent_handle));
-
-    g_variant_builder_add(&builder, "{sv}", "timestamp",
-                          g_variant_new_uint32(timestamp));
-
-    g_variant_builder_add(&builder, "{sv}", "window-position",
-                          g_variant_new_string("center"));
-
-    return g_variant_builder_end(&builder);
+      idle_.reset(new glib::Timeout(50, app_manager_not_synced));
   }
 
   GnomeFileManager* parent_;
   glib::DBusProxy filemanager_proxy_;
   glib::Source::UniquePtr idle_;
-  std::map<ApplicationWindowPtr, std::string> opened_location_for_window_;
+  std::map<Window, std::string> opened_location_for_xid_;
 };
 
 
@@ -214,29 +185,22 @@ bool GnomeFileManager::TrashFile(std::string const& uri)
   return false;
 }
 
-void GnomeFileManager::EmptyTrash(uint64_t timestamp, Window parent_xid)
+void GnomeFileManager::EmptyTrash(uint64_t timestamp)
 {
-  auto const& proxy = impl_->NautilusOperationsProxy();
-  const bool ask_confirmation = true;
-
-  GVariantBuilder b;
-  g_variant_builder_init(&b, G_VARIANT_TYPE("(ba{sv})"));
-  g_variant_builder_add(&b, "b", ask_confirmation);
-  g_variant_builder_add_value(&b, impl_->GetPlatformData(timestamp, parent_xid));
-  glib::Variant parameters(g_variant_builder_end(&b));
+  auto const& proxy = impl_->NemoOperationsProxy();
 
   // Passing the proxy to the lambda we ensure that it will be destroyed when needed
-  proxy->CallBegin("EmptyTrash", parameters, [proxy] (GVariant*, glib::Error const&) {});
+  proxy->CallBegin("EmptyTrashWithTimestamp", g_variant_new("(u)", static_cast<guint32>(timestamp)), [proxy] (GVariant*, glib::Error const&) {});
 }
 
-void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp, Window parent_xid)
+void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp)
 {
   if (uris.empty() || dest.empty())
     return;
 
   bool found_valid = false;
   GVariantBuilder b;
-  g_variant_builder_init(&b, G_VARIANT_TYPE("(assa{sv})"));
+  g_variant_builder_init(&b, G_VARIANT_TYPE("(assu)"));
   g_variant_builder_open(&b, G_VARIANT_TYPE("as"));
 
   for (auto const& uri : uris)
@@ -250,23 +214,25 @@ void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string
 
   g_variant_builder_close(&b);
   g_variant_builder_add(&b, "s", dest.c_str());
-  g_variant_builder_add_value(&b, impl_->GetPlatformData(timestamp, parent_xid));
+  g_variant_builder_add(&b, "u", static_cast<guint32>(timestamp));
   glib::Variant parameters(g_variant_builder_end(&b));
 
   if (found_valid)
   {
     // Passing the proxy to the lambda we ensure that it will be destroyed when needed
-    auto const& proxy = impl_->NautilusOperationsProxy();
-    proxy->CallBegin("CopyURIs", parameters, [proxy] (GVariant*, glib::Error const&) {});
+    auto const& proxy = impl_->NemoOperationsProxy();
+    proxy->CallBegin("CopyURIsWithTimestamp", parameters, [proxy] (GVariant*, glib::Error const&) {});
   }
 }
 
 WindowList GnomeFileManager::WindowsForLocation(std::string const& location) const
 {
   std::vector<ApplicationWindowPtr> windows;
+  auto& app_manager = ApplicationManager::Default();
+
   glib::Object<GFile> location_file(g_file_new_for_uri(location.c_str()));
 
-  for (auto const& pair : impl_->opened_location_for_window_)
+  for (auto const& pair : impl_->opened_location_for_xid_)
   {
     auto const& loc = pair.second;
     bool matches = (loc == location);
@@ -280,7 +246,7 @@ WindowList GnomeFileManager::WindowsForLocation(std::string const& location) con
 
     if (matches)
     {
-      auto const& win = pair.first;
+      auto const& win = app_manager.GetWindowForId(pair.first);
 
       if (win && std::find(windows.rbegin(), windows.rend(), win) == windows.rend())
         windows.push_back(win);
@@ -294,9 +260,9 @@ std::string GnomeFileManager::LocationForWindow(ApplicationWindowPtr const& win)
 {
   if (win)
   {
-    auto it = impl_->opened_location_for_window_.find(win);
+    auto it = impl_->opened_location_for_xid_.find(win->window_id());
 
-    if (it != end(impl_->opened_location_for_window_))
+    if (it != end(impl_->opened_location_for_xid_))
       return it->second;
   }
 
diff --git a/unity-shared/GnomeFileManager.h b/unity-shared/GnomeFileManager.h
index 6fa53a6..4500a2b 100644
--- a/unity-shared/GnomeFileManager.h
+++ b/unity-shared/GnomeFileManager.h
@@ -35,9 +35,9 @@ public:
   void Open(std::string const& uri, uint64_t timestamp);
   void OpenTrash(uint64_t timestamp);
 
-  void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp, Window parent_xid);
+  void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp);
   bool TrashFile(std::string const& uri);
-  void EmptyTrash(uint64_t timestamp, Window parent_xid);
+  void EmptyTrash(uint64_t timestamp);
 
   WindowList WindowsForLocation(std::string const& location) const;
   std::string LocationForWindow(ApplicationWindowPtr const&) const;
-- 
2.52.0

