From 3fa2d53ffa7ef8a9ab44b8932be6b198025d9a71 Mon Sep 17 00:00:00 2001
From: Julien Bonjean <julien@bonjean.info>
Date: Thu, 11 Mar 2010 14:45:24 -0500
Subject: [PATCH] [#2916] Added duplicate shortcut keys protection

---
 .../src/config/shortcuts-config.c             | 25 +++++++++---
 sflphone-client-gnome/src/shortcuts.c         | 38 +++++++++++++++----
 sflphone-client-gnome/src/shortcuts.h         | 33 ++++++++--------
 3 files changed, 69 insertions(+), 27 deletions(-)

diff --git a/sflphone-client-gnome/src/config/shortcuts-config.c b/sflphone-client-gnome/src/config/shortcuts-config.c
index b343f52071..06eb1839a9 100644
--- a/sflphone-client-gnome/src/config/shortcuts-config.c
+++ b/sflphone-client-gnome/src/config/shortcuts-config.c
@@ -26,7 +26,7 @@ GtkWidget*
 create_shortcuts_settings()
 {
   GtkWidget *vbox, *result_frame, *window, *treeview, *scrolled_window, *label;
-  GtkListStore *store;
+
   GtkTreeIter iter;
   guint i = 0;
 
@@ -40,7 +40,7 @@ create_shortcuts_settings()
   treeview = gtk_tree_view_new();
   setup_tree_view(treeview);
 
-  store = gtk_list_store_new(COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT);
+  GtkListStore *store = gtk_list_store_new(COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_UINT);
 
   Accelerator* list = shortcuts_get_list();
 
@@ -100,14 +100,29 @@ accel_edited(GtkCellRendererAccel *renderer, gchar *path, guint accel_key,
   GtkTreeModel *model;
   GtkTreeIter iter;
 
-  // Update treeview
+  Accelerator* list = shortcuts_get_list();
   model = gtk_tree_view_get_model(treeview);
+  gint code = XKeysymToKeycode(GDK_DISPLAY(), accel_key);
+
+  // Disable existing binding if key already used
+  int i = 0;
+  gtk_tree_model_get_iter_first(model, &iter);
+  while (list[i].action != NULL)
+      {
+          if(list[i].value == code)
+            {
+              gtk_list_store_set(GTK_LIST_STORE (model), &iter, MASK, 0, VALUE, 0, -1);
+              WARN("This key was already affected");
+            }
+          gtk_tree_model_iter_next(model, &iter);
+          i++;
+      }
+
+  // Update treeview
   if (gtk_tree_model_get_iter_from_string(model, &iter, path))
     gtk_list_store_set(GTK_LIST_STORE (model), &iter, MASK, (gint) mask, VALUE,
         accel_key, -1);
 
-  gint code = XKeysymToKeycode(GDK_DISPLAY(), accel_key);
-
   // Update GDK bindings
   shortcuts_update_bindings(atoi(path), code);
 }
diff --git a/sflphone-client-gnome/src/shortcuts.c b/sflphone-client-gnome/src/shortcuts.c
index e52e5f109b..c87d9b8cc9 100644
--- a/sflphone-client-gnome/src/shortcuts.c
+++ b/sflphone-client-gnome/src/shortcuts.c
@@ -225,6 +225,35 @@ initialize_accelerators_list ()
   accelerators_list[index].value = 0;
 }
 
+static void
+update_bindings_data(const guint index, const guint code)
+{
+    // we need to be sure this code is not already affected
+    // to another action
+    int i = 0;
+    while (accelerators_list[i].action != NULL)
+      {
+        if(accelerators_list[i].value == code)
+          {
+            // disable old binding
+            accelerators_list[i].value = 0;
+
+            // update config table
+            g_hash_table_replace (shortcutsMap,
+                  g_strdup (accelerators_list[i].action), GINT_TO_POINTER (0));
+          }
+        i++;
+      }
+
+  // store new value
+  accelerators_list[index].value = code;
+
+  // update value in hashtable (used for dbus calls)
+  g_hash_table_replace (shortcutsMap,
+      g_strdup (accelerators_list[index].action), GINT_TO_POINTER (
+          accelerators_list[index].value));
+}
+
 /*
  * "Public" functions
  */
@@ -238,13 +267,8 @@ shortcuts_update_bindings (const guint index, const guint code)
   // first remove all existing bindings
   remove_bindings ();
 
-  // store new value
-  accelerators_list[index].value = code;
-
-  // update value in hashtable (used for dbus calls)
-  g_hash_table_replace (shortcutsMap,
-      g_strdup (accelerators_list[index].action), GINT_TO_POINTER (
-          accelerators_list[index].value));
+  // update data
+  update_bindings_data(index, code);
 
   // recreate all bindings
   create_bindings ();
diff --git a/sflphone-client-gnome/src/shortcuts.h b/sflphone-client-gnome/src/shortcuts.h
index e5e512d5ea..dcad5019eb 100644
--- a/sflphone-client-gnome/src/shortcuts.h
+++ b/sflphone-client-gnome/src/shortcuts.h
@@ -26,53 +26,56 @@ typedef struct
   GdkModifierType mask;
   guint value;
   void
-  (*callback)(void);
+  (*callback) (void);
 } Accelerator;
 
 static void
-grab_key(int key_code, GdkWindow *root);
+grab_key (int key_code, GdkWindow *root);
 
 static void
-ungrab_key(int key_code, GdkWindow *root);
+ungrab_key (int key_code, GdkWindow *root);
 
 static GdkFilterReturn
-filter_keys(GdkXEvent *xevent, GdkEvent *event, gpointer data);
+filter_keys (GdkXEvent *xevent, GdkEvent *event, gpointer data);
 
 static void
-remove_bindings();
+remove_bindings ();
 
 static void
-create_bindings();
+create_bindings ();
 
 static void
-pick_up_callback();
+pick_up_callback ();
 
 static void
-hang_up_callback();
+hang_up_callback ();
 
 static void
-initialize_binding(const gchar* action, const guint code);
+initialize_binding (const gchar* action, const guint code);
 
 static void
-initialize_shortcuts_keys();
+initialize_shortcuts_keys ();
 
 static void*
-get_action_callback(const gchar* action);
+get_action_callback (const gchar* action);
+
+static void
+update_bindings_data (const guint index, const guint code);
 
 /*
  * "Public" functions
  */
 
 void
-shortcuts_initialize_bindings();
+shortcuts_initialize_bindings ();
 
 void
-shortcuts_update_bindings(const guint index, const guint code);
+shortcuts_update_bindings (const guint index, const guint code);
 
 void
-shortcuts_destroy_bindings();
+shortcuts_destroy_bindings ();
 
 Accelerator*
-shortcuts_get_list();
+shortcuts_get_list ();
 
 #endif /* SHORTCUTS_H_ */
-- 
GitLab