app: check and clean out duplicate accelerators on startup.
Duplicate accelerators are not supposed to happen. It is not possible to set them through the GUI in particular. Nevertheless gtk_accel_map_load() would apparently let duplicates pass, which could happen after editing the menurc directly, or using the development version (no action name migration happens there), or simply after a potential bug. This is then very annoying because you may see several actions displaying the same shortcut but only one actually work. And trying to re-set through GUI the shortcut to the one action you wish to run does not fix the duplicate issue (you have to laboriously find which other action use the same accelerator and delete it first). Better be safe than sorry and make a quick check at startup, then delete the accelerator on one of the duplicates (you can't guess which one was actually wanted, but at least you will facilitate manual reset through the GUI).
This commit is contained in:
@ -135,6 +135,17 @@ static void gui_display_changed (GimpContext *context,
|
||||
GimpDisplay *display,
|
||||
Gimp *gimp);
|
||||
|
||||
static void gui_compare_accelerator (gpointer data,
|
||||
const gchar *accel_path,
|
||||
guint accel_key,
|
||||
GdkModifierType accel_mods,
|
||||
gboolean changed);
|
||||
static void gui_check_unique_accelerator (gpointer data,
|
||||
const gchar *accel_path,
|
||||
guint accel_key,
|
||||
GdkModifierType accel_mods,
|
||||
gboolean changed);
|
||||
|
||||
|
||||
/* private variables */
|
||||
|
||||
@ -530,6 +541,10 @@ gui_restore_after_callback (Gimp *gimp,
|
||||
gui_config->tearoff_menus);
|
||||
gimp_ui_manager_update (image_ui_manager, gimp);
|
||||
|
||||
/* Check that every accelerator is unique. */
|
||||
gtk_accel_map_foreach_unfiltered (NULL,
|
||||
gui_check_unique_accelerator);
|
||||
|
||||
gimp_action_history_init (gimp);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
@ -861,3 +876,50 @@ gui_display_changed (GimpContext *context,
|
||||
|
||||
gimp_ui_manager_update (image_ui_manager, display);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *path;
|
||||
guint key;
|
||||
GdkModifierType mods;
|
||||
}
|
||||
accelData;
|
||||
|
||||
static void
|
||||
gui_compare_accelerator (gpointer data,
|
||||
const gchar *accel_path,
|
||||
guint accel_key,
|
||||
GdkModifierType accel_mods,
|
||||
gboolean changed)
|
||||
{
|
||||
accelData *accel = data;
|
||||
|
||||
if (accel->key == accel_key && accel->mods == accel_mods &&
|
||||
g_strcmp0 (accel->path, accel_path))
|
||||
{
|
||||
g_warning ("Actions \"%s\" and \"%s\" use the same accelerator.\n"
|
||||
"Disable the accelerator on \"%s\".",
|
||||
accel->path, accel_path, accel_path);
|
||||
gtk_accel_map_change_entry (accel_path, 0, 0, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gui_check_unique_accelerator (gpointer data,
|
||||
const gchar *accel_path,
|
||||
guint accel_key,
|
||||
GdkModifierType accel_mods,
|
||||
gboolean changed)
|
||||
{
|
||||
if (gtk_accelerator_valid (accel_key, accel_mods))
|
||||
{
|
||||
accelData accel;
|
||||
|
||||
accel.path = accel_path;
|
||||
accel.key = accel_key;
|
||||
accel.mods = accel_mods;
|
||||
|
||||
gtk_accel_map_foreach_unfiltered (&accel,
|
||||
gui_compare_accelerator);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user