From 68f2888d3133b183b5e0521b9503e99dc78d3b2c Mon Sep 17 00:00:00 2001 From: Alex Schumann Date: Thu, 23 Jul 2026 10:06:52 -0700 Subject: [PATCH 1/2] cinnamon-desktop-editor.py: Don't hang the panel launcher edit dialog when the edited entry is missing from launcherList. list.index() raises ValueError rather than returning -1 (the dead 'if i >= 0:' check suggests indexOf-style semantics were assumed). The unhandled exception in the dialog callback meant Gtk.main_quit() was never reached, leaving the dialog open forever and an orphaned cinnamon-custom-launcher-N.desktop file behind on every attempt. Ref: #13895 --- .../cinnamon-desktop-editor.py | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py index ba879b4a2b..76e48b40bd 100755 --- a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py +++ b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py @@ -415,20 +415,29 @@ def launcher_cb(self, success, dest_path): self.end() def panel_launcher_cb(self, success, dest_path): - if success: - settings = JsonSettingsWidgets.JSONSettingsHandler(self.json_path) - launchers = settings.get_value("launcherList") - if self.desktop_file is None: - launchers.append(os.path.split(dest_path)[1]) - else: - i = launchers.index(self.desktop_file) - if i >= 0: - del launchers[i] - launchers.insert(i, os.path.split(dest_path)[1]) - settings.save_settings() - if self.desktop_file is None: - self.ask_menu_launcher(dest_path) - self.end() + try: + if success: + settings = JsonSettingsWidgets.JSONSettingsHandler(self.json_path) + launchers = settings.get_value("launcherList") + new_name = os.path.split(dest_path)[1] + if self.desktop_file is None: + launchers.append(new_name) + else: + try: + i = launchers.index(self.desktop_file) + except ValueError: + # The entry we were asked to edit is no longer in the + # list (a previous edit may have already replaced it) - + # add the new launcher instead of dropping the edit. + if new_name not in launchers: + launchers.append(new_name) + else: + launchers[i] = new_name + settings.save_settings() + if self.desktop_file is None: + self.ask_menu_launcher(dest_path) + finally: + self.end() def nemo_launcher_cb(self, success, dest_path): if success: From a6bff17582fadb51027708522b27812e2d5e3712 Mon Sep 17 00:00:00 2001 From: Alex Schumann Date: Thu, 23 Jul 2026 10:07:08 -0700 Subject: [PATCH 2/2] cinnamon-desktop-editor.py: Notify Cinnamon after changing launcherList so the panel updates without a restart. Cinnamon does not monitor xlet settings files - external changes only reach a running xlet via the org.Cinnamon updateSetting dbus method, which xlet-settings.py already uses after saving. Without this, an edited or added panel launcher didn't appear until Cinnamon was restarted, which also baited users into re-editing and hitting the stale-entry case. Ref: #13895 --- .../cinnamon-desktop-editor.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py index 76e48b40bd..e843ce4256 100755 --- a/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py +++ b/files/usr/share/cinnamon/cinnamon-desktop-editor/cinnamon-desktop-editor.py @@ -4,6 +4,7 @@ import os import gettext import glob +import json from optparse import OptionParser import shutil import subprocess @@ -434,11 +435,24 @@ def panel_launcher_cb(self, success, dest_path): else: launchers[i] = new_name settings.save_settings() + self.notify_cinnamon(launchers) if self.desktop_file is None: self.ask_menu_launcher(dest_path) finally: self.end() + def notify_cinnamon(self, launchers): + # Cinnamon does not monitor the settings file for external changes - + # tell it to reload, the same way xlet-settings.py does after saving. + uuid = os.path.basename(os.path.dirname(self.json_path)) + instance_id = os.path.splitext(os.path.basename(self.json_path))[0] + try: + proxy = Gio.DBusProxy.new_for_bus_sync(Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None, + "org.Cinnamon", "/org/Cinnamon", "org.Cinnamon", None) + proxy.updateSetting('(ssss)', uuid, instance_id, "launcherList", json.dumps(launchers)) + except GLib.Error as e: + print("Could not notify Cinnamon of launcher list change: %s" % e.message) + def nemo_launcher_cb(self, success, dest_path): if success: self.ask_menu_launcher(dest_path)