Home | History | Annotate | Download | only in patches
      1 --- control-center-2.10.1/capplets/keybindings/gnome-keybinding-properties.glade	Thu May 12 16:46:18 2005
      2 +++ control-center-2.10.1-new/capplets/keybindings/gnome-keybinding-properties.glade	Fri May 13 11:51:17 2005
      3 @@ -11,6 +11,11 @@
      4    <property name="modal">False</property>
      5    <property name="resizable">True</property>
      6    <property name="destroy_with_parent">False</property>
      7 +  <property name="decorated">True</property>
      8 +  <property name="skip_taskbar_hint">False</property>
      9 +  <property name="skip_pager_hint">False</property>
     10 +  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
     11 +  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
     12    <property name="has_separator">False</property>
     13  
     14    <child internal-child="vbox">
     15 @@ -32,6 +37,7 @@
     16  	      <property name="label">gtk-help</property>
     17  	      <property name="use_stock">True</property>
     18  	      <property name="relief">GTK_RELIEF_NORMAL</property>
     19 +	      <property name="focus_on_click">True</property>
     20  	      <property name="response_id">-11</property>
     21  	    </widget>
     22  	  </child>
     23 @@ -44,6 +50,7 @@
     24  	      <property name="label">gtk-close</property>
     25  	      <property name="use_stock">True</property>
     26  	      <property name="relief">GTK_RELIEF_NORMAL</property>
     27 +	      <property name="focus_on_click">True</property>
     28  	      <property name="response_id">-7</property>
     29  	    </widget>
     30  	  </child>
     31 @@ -152,6 +159,362 @@
     32  	      <property name="padding">0</property>
     33  	      <property name="expand">True</property>
     34  	      <property name="fill">True</property>
     35 +	    </packing>
     36 +	  </child>
     37 +
     38 +	  <child>
     39 +	    <widget class="GtkHBox" id="hbox2">
     40 +	      <property name="border_width">5</property>
     41 +	      <property name="visible">True</property>
     42 +	      <property name="homogeneous">False</property>
     43 +	      <property name="spacing">6</property>
     44 +
     45 +	      <child>
     46 +		<widget class="GtkLabel" id="label13">
     47 +		  <property name="visible">True</property>
     48 +		  <property name="label" translatable="yes" comments="SUN_BRANDING">Custom Shortcuts:</property>
     49 +		  <property name="use_underline">False</property>
     50 +		  <property name="use_markup">False</property>
     51 +		  <property name="justify">GTK_JUSTIFY_LEFT</property>
     52 +		  <property name="wrap">False</property>
     53 +		  <property name="selectable">False</property>
     54 +		  <property name="xalign">0.5</property>
     55 +		  <property name="yalign">0.5</property>
     56 +		  <property name="xpad">0</property>
     57 +		  <property name="ypad">0</property>
     58 +		</widget>
     59 +		<packing>
     60 +		  <property name="padding">0</property>
     61 +		  <property name="expand">False</property>
     62 +		  <property name="fill">False</property>
     63 +		</packing>
     64 +	      </child>
     65 +
     66 +	      <child>
     67 +		<widget class="GtkButton" id="add_custom_button">
     68 +		  <property name="width_request">60</property>
     69 +		  <property name="height_request">30</property>
     70 +		  <property name="visible">True</property>
     71 +		  <property name="can_focus">True</property>
     72 +		  <property name="label">gtk-new</property>
     73 +		  <property name="use_stock">True</property>
     74 +		  <property name="relief">GTK_RELIEF_NORMAL</property>
     75 +		  <property name="focus_on_click">True</property>
     76 +		</widget>
     77 +		<packing>
     78 +		  <property name="padding">0</property>
     79 +		  <property name="expand">True</property>
     80 +		  <property name="fill">True</property>
     81 +		</packing>
     82 +	      </child>
     83 +
     84 +	      <child>
     85 +		<widget class="GtkButton" id="edit_custom_button">
     86 +		  <property name="visible">True</property>
     87 +		  <property name="can_focus">True</property>
     88 +		  <property name="relief">GTK_RELIEF_NORMAL</property>
     89 +		  <property name="focus_on_click">True</property>
     90 +
     91 +		  <child>
     92 +		    <widget class="GtkAlignment" id="alignment1">
     93 +		      <property name="visible">True</property>
     94 +		      <property name="xalign">0.5</property>
     95 +		      <property name="yalign">0.5</property>
     96 +		      <property name="xscale">0</property>
     97 +		      <property name="yscale">0</property>
     98 +		      <property name="top_padding">0</property>
     99 +		      <property name="bottom_padding">0</property>
    100 +		      <property name="left_padding">0</property>
    101 +		      <property name="right_padding">0</property>
    102 +
    103 +		      <child>
    104 +			<widget class="GtkHBox" id="hbox3">
    105 +			  <property name="visible">True</property>
    106 +			  <property name="homogeneous">False</property>
    107 +			  <property name="spacing">2</property>
    108 +
    109 +			  <child>
    110 +			    <widget class="GtkImage" id="image2">
    111 +			      <property name="visible">True</property>
    112 +			      <property name="stock">gtk-preferences</property>
    113 +			      <property name="icon_size">4</property>
    114 +			      <property name="xalign">0.5</property>
    115 +			      <property name="yalign">0.5</property>
    116 +			      <property name="xpad">0</property>
    117 +			      <property name="ypad">0</property>
    118 +			    </widget>
    119 +			    <packing>
    120 +			      <property name="padding">0</property>
    121 +			      <property name="expand">False</property>
    122 +			      <property name="fill">False</property>
    123 +			    </packing>
    124 +			  </child>
    125 +
    126 +			  <child>
    127 +			    <widget class="GtkLabel" id="label14">
    128 +			      <property name="visible">True</property>
    129 +			      <property name="label" translatable="yes" comments="SUN_BRANDING">_Edit...</property>
    130 +			      <property name="use_underline">True</property>
    131 +			      <property name="use_markup">False</property>
    132 +			      <property name="justify">GTK_JUSTIFY_LEFT</property>
    133 +			      <property name="wrap">False</property>
    134 +			      <property name="selectable">False</property>
    135 +			      <property name="xalign">0.5</property>
    136 +			      <property name="yalign">0.5</property>
    137 +			      <property name="xpad">0</property>
    138 +			      <property name="ypad">0</property>
    139 +			    </widget>
    140 +			    <packing>
    141 +			      <property name="padding">0</property>
    142 +			      <property name="expand">False</property>
    143 +			      <property name="fill">False</property>
    144 +			    </packing>
    145 +			  </child>
    146 +			</widget>
    147 +		      </child>
    148 +		    </widget>
    149 +		  </child>
    150 +		</widget>
    151 +		<packing>
    152 +		  <property name="padding">0</property>
    153 +		  <property name="expand">True</property>
    154 +		  <property name="fill">True</property>
    155 +		</packing>
    156 +	      </child>
    157 +
    158 +	      <child>
    159 +		<widget class="GtkButton" id="disable_custom_button">
    160 +		  <property name="visible">True</property>
    161 +		  <property name="can_focus">True</property>
    162 +		  <property name="label">gtk-delete</property>
    163 +		  <property name="use_stock">True</property>
    164 +		  <property name="relief">GTK_RELIEF_NORMAL</property>
    165 +		  <property name="focus_on_click">True</property>
    166 +		</widget>
    167 +		<packing>
    168 +		  <property name="padding">0</property>
    169 +		  <property name="expand">True</property>
    170 +		  <property name="fill">True</property>
    171 +		</packing>
    172 +	      </child>
    173 +	    </widget>
    174 +	    <packing>
    175 +	      <property name="padding">0</property>
    176 +	      <property name="expand">False</property>
    177 +	      <property name="fill">False</property>
    178 +	      <property name="pack_type">GTK_PACK_END</property>
    179 +	    </packing>
    180 +	  </child>
    181 +	</widget>
    182 +	<packing>
    183 +	  <property name="padding">0</property>
    184 +	  <property name="expand">True</property>
    185 +	  <property name="fill">True</property>
    186 +	</packing>
    187 +      </child>
    188 +    </widget>
    189 +  </child>
    190 +</widget>
    191 +
    192 +<widget class="GtkDialog" id="custom-binding-dialog">
    193 +  <property name="visible">True</property>
    194 +  <property name="title" translatable="yes" comments="SUN_BRANDING">Custom Binding</property>
    195 +  <property name="type">GTK_WINDOW_TOPLEVEL</property>
    196 +  <property name="window_position">GTK_WIN_POS_NONE</property>
    197 +  <property name="modal">False</property>
    198 +  <property name="resizable">True</property>
    199 +  <property name="destroy_with_parent">False</property>
    200 +  <property name="decorated">True</property>
    201 +  <property name="skip_taskbar_hint">False</property>
    202 +  <property name="skip_pager_hint">False</property>
    203 +  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
    204 +  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
    205 +  <property name="has_separator">True</property>
    206 +  <accessibility>
    207 +    <atkproperty name="AtkObject::accessible_name" translatable="yes" comments="SUN_BRANDING">Custom Binding</atkproperty>
    208 +  </accessibility>
    209 +
    210 +  <child internal-child="vbox">
    211 +    <widget class="GtkVBox" id="dialog-vbox1">
    212 +      <property name="visible">True</property>
    213 +      <property name="homogeneous">False</property>
    214 +      <property name="spacing">0</property>
    215 +
    216 +      <child internal-child="action_area">
    217 +	<widget class="GtkHButtonBox" id="dialog-action_area2">
    218 +	  <property name="visible">True</property>
    219 +	  <property name="layout_style">GTK_BUTTONBOX_END</property>
    220 +
    221 +	  <child>
    222 +	    <widget class="GtkButton" id="helpbutton2">
    223 +	      <property name="visible">True</property>
    224 +	      <property name="can_default">True</property>
    225 +	      <property name="can_focus">True</property>
    226 +	      <property name="label">gtk-help</property>
    227 +	      <property name="use_stock">True</property>
    228 +	      <property name="relief">GTK_RELIEF_NORMAL</property>
    229 +	      <property name="focus_on_click">True</property>
    230 +	      <property name="response_id">-11</property>
    231 +	    </widget>
    232 +	  </child>
    233 +
    234 +	  <child>
    235 +	    <widget class="GtkButton" id="cancelbutton1">
    236 +	      <property name="visible">True</property>
    237 +	      <property name="can_default">True</property>
    238 +	      <property name="can_focus">True</property>
    239 +	      <property name="label">gtk-cancel</property>
    240 +	      <property name="use_stock">True</property>
    241 +	      <property name="relief">GTK_RELIEF_NORMAL</property>
    242 +	      <property name="focus_on_click">True</property>
    243 +	      <property name="response_id">-6</property>
    244 +	    </widget>
    245 +	  </child>
    246 +
    247 +	  <child>
    248 +	    <widget class="GtkButton" id="okbutton1">
    249 +	      <property name="visible">True</property>
    250 +	      <property name="can_default">True</property>
    251 +	      <property name="can_focus">True</property>
    252 +	      <property name="label">gtk-ok</property>
    253 +	      <property name="use_stock">True</property>
    254 +	      <property name="relief">GTK_RELIEF_NORMAL</property>
    255 +	      <property name="focus_on_click">True</property>
    256 +	      <property name="response_id">-5</property>
    257 +	    </widget>
    258 +	  </child>
    259 +	</widget>
    260 +	<packing>
    261 +	  <property name="padding">0</property>
    262 +	  <property name="expand">False</property>
    263 +	  <property name="fill">True</property>
    264 +	  <property name="pack_type">GTK_PACK_END</property>
    265 +	</packing>
    266 +      </child>
    267 +
    268 +      <child>
    269 +	<widget class="GtkHBox" id="hbox5">
    270 +	  <property name="visible">True</property>
    271 +	  <property name="homogeneous">False</property>
    272 +	  <property name="spacing">0</property>
    273 +
    274 +	  <child>
    275 +	    <widget class="GtkLabel" id="label15">
    276 +	      <property name="visible">True</property>
    277 +	      <property name="label" translatable="yes" comments="SUN_BRANDING">_New Command: </property>
    278 +	      <property name="use_underline">True</property>
    279 +	      <property name="use_markup">False</property>
    280 +	      <property name="justify">GTK_JUSTIFY_LEFT</property>
    281 +	      <property name="wrap">False</property>
    282 +	      <property name="selectable">False</property>
    283 +	      <property name="xalign">0.5</property>
    284 +	      <property name="yalign">0.5</property>
    285 +	      <property name="xpad">0</property>
    286 +	      <property name="ypad">0</property>
    287 +	    </widget>
    288 +	    <packing>
    289 +	      <property name="padding">0</property>
    290 +	      <property name="expand">False</property>
    291 +	      <property name="fill">False</property>
    292 +	    </packing>
    293 +	  </child>
    294 +
    295 +	  <child>
    296 +	    <widget class="GtkEntry" id="action_tf">
    297 +	      <property name="visible">True</property>
    298 +	      <property name="can_focus">True</property>
    299 +	      <property name="editable">True</property>
    300 +	      <property name="visibility">True</property>
    301 +	      <property name="max_length">0</property>
    302 +	      <property name="text" translatable="yes"></property>
    303 +	      <property name="has_frame">True</property>
    304 +	      <property name="invisible_char" translatable="yes">*</property>
    305 +	      <property name="activates_default">False</property>
    306 +	      <accessibility>
    307 +		<atkproperty name="AtkObject::accessible_name" translatable="yes">action_tf</atkproperty>
    308 +	      </accessibility>
    309 +	    </widget>
    310 +	    <packing>
    311 +	      <property name="padding">0</property>
    312 +	      <property name="expand">True</property>
    313 +	      <property name="fill">True</property>
    314 +	    </packing>
    315 +	  </child>
    316 +
    317 +	  <child>
    318 +	    <widget class="GtkButton" id="browse_button">
    319 +	      <property name="visible">True</property>
    320 +	      <property name="can_focus">True</property>
    321 +	      <property name="relief">GTK_RELIEF_NORMAL</property>
    322 +	      <property name="focus_on_click">True</property>
    323 +	      <accessibility>
    324 +		<atkproperty name="AtkObject::accessible_name" translatable="yes" comments="SUN_BRANDING">Browse</atkproperty>
    325 +	      </accessibility>
    326 +
    327 +	      <child>
    328 +		<widget class="GtkAlignment" id="alignment2">
    329 +		  <property name="visible">True</property>
    330 +		  <property name="xalign">0.5</property>
    331 +		  <property name="yalign">0.5</property>
    332 +		  <property name="xscale">0</property>
    333 +		  <property name="yscale">0</property>
    334 +		  <property name="top_padding">0</property>
    335 +		  <property name="bottom_padding">0</property>
    336 +		  <property name="left_padding">0</property>
    337 +		  <property name="right_padding">0</property>
    338 +
    339 +		  <child>
    340 +		    <widget class="GtkHBox" id="hbox6">
    341 +		      <property name="visible">True</property>
    342 +		      <property name="homogeneous">False</property>
    343 +		      <property name="spacing">2</property>
    344 +
    345 +		      <child>
    346 +			<widget class="GtkImage" id="image3">
    347 +			  <property name="visible">True</property>
    348 +			  <property name="stock">gtk-open</property>
    349 +			  <property name="icon_size">4</property>
    350 +			  <property name="xalign">0.5</property>
    351 +			  <property name="yalign">0.5</property>
    352 +			  <property name="xpad">0</property>
    353 +			  <property name="ypad">0</property>
    354 +			</widget>
    355 +			<packing>
    356 +			  <property name="padding">0</property>
    357 +			  <property name="expand">False</property>
    358 +			  <property name="fill">False</property>
    359 +			</packing>
    360 +		      </child>
    361 +
    362 +		      <child>
    363 +			<widget class="GtkLabel" id="label16">
    364 +			  <property name="visible">True</property>
    365 +			  <property name="label" translatable="yes" comments="SUN_BRANDING">_Browse</property>
    366 +			  <property name="use_underline">True</property>
    367 +			  <property name="use_markup">False</property>
    368 +			  <property name="justify">GTK_JUSTIFY_LEFT</property>
    369 +			  <property name="wrap">False</property>
    370 +			  <property name="selectable">False</property>
    371 +			  <property name="xalign">0.5</property>
    372 +			  <property name="yalign">0.5</property>
    373 +			  <property name="xpad">0</property>
    374 +			  <property name="ypad">0</property>
    375 +			</widget>
    376 +			<packing>
    377 +			  <property name="padding">0</property>
    378 +			  <property name="expand">False</property>
    379 +			  <property name="fill">False</property>
    380 +			</packing>
    381 +		      </child>
    382 +		    </widget>
    383 +		  </child>
    384 +		</widget>
    385 +	      </child>
    386 +	    </widget>
    387 +	    <packing>
    388 +	      <property name="padding">0</property>
    389 +	      <property name="expand">False</property>
    390 +	      <property name="fill">False</property>
    391  	    </packing>
    392  	  </child>
    393  	</widget>
    394 --- gnome-control-center-2.19.91/capplets/keybindings/Makefile.am-clean	2007-05-02 11:42:01.000000000 +0100
    395 +++ gnome-control-center-2.19.91/capplets/keybindings/Makefile.am	2007-09-03 15:31:23.316179000 +0100
    396 @@ -6,6 +6,8 @@
    397  gnome_keybinding_properties_LDADD = $(GNOMECC_CAPPLETS_LIBS)
    398  gnome_keybinding_properties_SOURCES = 	\
    399  	gnome-keybinding-properties.c	\
    400 +	custom-binding.c		\
    401 +	custom-binding.h		\
    402  	eggcellrendererkeys.c		\
    403  	eggcellrendererkeys.h		\
    404  	eggaccelerators.c		\
    405 
    406 --- gnome-control-center-2.19.91/capplets/keybindings/custom-binding.c.orig	2007-09-05 14:22:28.103863000 +0100
    407 +++ gnome-control-center-2.19.91/capplets/keybindings/custom-binding.c	2007-09-05 14:26:14.588448000 +0100
    408 @@ -0,0 +1,516 @@
    409 +/* Erwann Chenede 2002 */
    410 +
    411 +#include <config.h>
    412 +
    413 +#include <string.h>
    414 +#include <gtk/gtk.h>
    415 +#include <gconf/gconf-client.h>
    416 +#include <gdk/gdkx.h>
    417 +#include <glade/glade.h>
    418 +#include <X11/Xatom.h>
    419 +
    420 +#include "wm-common.h"
    421 +#include "capplet-util.h"
    422 +#include "eggcellrendererkeys.h"
    423 +#include "activate-settings-daemon.h"
    424 +#include "custom-binding.h"
    425 +
    426 +extern KeyListEntry *custom_binding_list;
    427 +extern GladeXML *main_dialog;
    428 +
    429 +void
    430 +my_verbose (const char *format, ...)
    431 +{
    432 +  va_list args;
    433 +  gchar *str;
    434 +
    435 +  if (format == NULL)
    436 +    return;
    437 +
    438 +  if (1) /*DEBUG*/
    439 +    return;
    440 +  
    441 +  va_start (args, format);
    442 +  str = g_strdup_vprintf (format, args);
    443 +  va_end (args);
    444 +  
    445 +  fputs (str, stderr);
    446 +
    447 +  fflush (stderr);
    448 +  
    449 +  g_free (str);
    450 +}
    451 +
    452 +void
    453 +cmd_line_changed (GConfClient *client,
    454 +		  guint        cnxn_id,
    455 +		  GConfEntry  *entry,
    456 +		  gpointer     user_data)
    457 +{
    458 +  KeyEntry *key_entry;
    459 +
    460 +  my_verbose ("In cmd_line_changed\n");
    461 +  
    462 +  key_entry = (KeyEntry *)user_data;
    463 +  g_free (key_entry->action);
    464 +  key_entry->action = g_strdup (gconf_value_get_string (entry->value));
    465 +  key_entry->editable = gconf_entry_get_is_writable (entry);
    466 +
    467 +  /* update the model */
    468 +  gtk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry);
    469 +}
    470 +
    471 +KeyEntry *
    472 +find_keyentry_selected (GtkTreeView *tree_view)
    473 +{
    474 +  GtkTreeSelection* sel = NULL;
    475 +  sel = gtk_tree_view_get_selection (tree_view);
    476 +  
    477 +  if (sel)
    478 +    {
    479 +      GtkTreeIter iter;
    480 +      GtkTreeModel *model;
    481 +      if (gtk_tree_selection_get_selected (sel, &model, &iter))
    482 +	{
    483 +	  KeyEntry *key_entry;
    484 +
    485 +	  gtk_tree_model_get (model, &iter, KEYENTRY_COLUMN, &key_entry, -1);
    486 +	  return key_entry;
    487 +	}
    488 +    }
    489 +  return NULL;
    490 +}
    491 +	
    492 +static gboolean key_delete_cleanup (KeyEntry *key_entry)
    493 +{
    494 +  GConfClient *client = gconf_client_get_default();
    495 +
    496 +  gconf_client_recursive_unset (client, key_entry->gconf_key, 0, NULL);
    497 +
    498 +  create_custom_bindings_list ();
    499 +  reload_key_entries (wm_common_get_current_window_manager(), main_dialog);
    500 +
    501 +  return FALSE;
    502 +}
    503 +
    504 +void 
    505 +disable_custom (GtkWidget *widget, GtkTreeView *tree_view)
    506 +{
    507 +  KeyEntry *key_entry = find_keyentry_selected (tree_view);
    508 +  
    509 +  if (key_entry)
    510 +    {
    511 +      if (key_entry->custom_key)
    512 +	{
    513 +	  GConfClient *client = gconf_client_get_default();
    514 +	  gchar *binding = g_strdup_printf ("%s/binding", key_entry->gconf_key);
    515 +	  gchar *binding_str;
    516 +
    517 +	  gconf_client_notify_remove (client, key_entry->gconf_cnxn);
    518 +	  gconf_client_notify_remove (client, key_entry->cmd_line_cnxn);
    519 +
    520 +	  key_entry->gconf_cnxn = 0;
    521 +	  key_entry->cmd_line_cnxn = 0;
    522 +
    523 +	  binding_str = gconf_client_get_string (client,binding, NULL);
    524 +	
    525 +	  if (binding_str && strcmp (binding_str, "disabled")) {
    526 +		/* This is a neccessery evil. We need to follow a similar
    527 +		   pattern of sequence in setting the binding to disabled state
    528 +		   before deleting it. The timeout is to ensure that when
    529 +		   g-s-d is getting the changes it does not find a key which
    530 +		   is non-existent and crash.
    531 +		*/
    532 +		gconf_client_set_string (client,
    533 +					binding,
    534 +					"disabled",
    535 +					NULL);
    536 +	  	g_timeout_add (1000,  (GSourceFunc) key_delete_cleanup, key_entry);
    537 +
    538 +		g_free (binding_str);
    539 +	  } else 
    540 +		key_delete_cleanup (key_entry);
    541 +
    542 +	  g_free (binding);
    543 +	}
    544 +      else
    545 +	gconf_client_set_string (gconf_client_get_default(),key_entry->gconf_key, "", NULL);
    546 +    }
    547 +}
    548 +
    549 +static int
    550 +get_trailing_num (char *str)
    551 +{
    552 +  char **result = g_strsplit (str, "_", 2);
    553 +  int i = atoi (result[1]);
    554 +  g_strfreev (result);
    555 +  return i;
    556 +}
    557 +
    558 +static char *
    559 +find_free_custom_gconf_key ()
    560 +{
    561 +  GConfClient *client;
    562 +  GSList *list, *li;
    563 +  int num_bindings = 0;
    564 +  int max_num = 0;
    565 +  
    566 +  client  = gconf_client_get_default ();
    567 +
    568 +  list = gconf_client_all_dirs (client, GCONF_CUSTOM_BINDING_DIR, NULL);
    569 +
    570 +  num_bindings = g_slist_length (list);
    571 +
    572 +  custom_binding_list = g_new0 (KeyListEntry, num_bindings+1);
    573 +
    574 +  /*find the highest num */
    575 +
    576 +  for (li = list; li != NULL; li = li->next)
    577 +    {
    578 +      char *subdir = li->data;
    579 +      char *key = g_path_get_basename(subdir);
    580 +      li->data = NULL;
    581 +
    582 +      if (g_ascii_strncasecmp(key, "custom_", 7) == 0)
    583 +	{
    584 +	  int i = get_trailing_num (key);
    585 +	  if (i > max_num)
    586 +	    max_num = i;
    587 +	}
    588 +    }
    589 +  g_slist_free (list);
    590 +  
    591 +  return g_strdup_printf ("%s/custom_%d",GCONF_CUSTOM_BINDING_DIR, max_num + 1);
    592 +}
    593 +
    594 +
    595 +static void 
    596 +add_real_key (GtkWidget *widget, GladeXML *dialog)
    597 +{
    598 +  KeyEntry *entry = NULL;
    599 +  GError *err = NULL;
    600 +  GtkWidget *area_tf = WID ("action_tf");
    601 +  char *binding_key, *action_key;
    602 +  char *action = g_strdup (gtk_entry_get_text (GTK_ENTRY (area_tf)));
    603 +
    604 +  entry = g_object_steal_data (G_OBJECT (area_tf), "key_entry");
    605 +  
    606 +  if (!entry)
    607 +    {
    608 +      char *new_gconf_key = find_free_custom_gconf_key ();
    609 +      GConfClient *client = gconf_client_get_default ();
    610 +      
    611 +      binding_key = g_strdup_printf ("%s/binding", new_gconf_key);
    612 +      action_key = g_strdup_printf ("%s/action", new_gconf_key);
    613 +      
    614 +      gconf_client_set_string (client, new_gconf_key, "", &err);
    615 +      
    616 +      gconf_client_set_string  (client, binding_key, "", &err);
    617 +      
    618 +      gconf_client_set_string  (client,	action_key, action, &err);
    619 +      
    620 +      create_custom_bindings_list ();
    621 +      reload_key_entries (wm_common_get_current_window_manager(), main_dialog);
    622 +      g_free (binding_key);
    623 +      g_free (new_gconf_key);
    624 +    }
    625 +  else
    626 +    {
    627 +      action_key = g_strdup_printf ("%s/action", entry->gconf_key);
    628 +      gconf_client_set_string  (gconf_client_get_default (),
    629 +				action_key, action, &err);
    630 +    }
    631 +
    632 +  g_free (action);
    633 +  g_free (action_key);
    634 +
    635 +  custom_cancel (widget, dialog);
    636 +}
    637 +
    638 +void 
    639 +custom_cancel (GtkWidget *widget, GladeXML *dialog)
    640 +{
    641 +  gtk_entry_set_text (GTK_ENTRY (WID ("action_tf")), "");
    642 +
    643 +  gtk_widget_hide (WID ("custom-binding-dialog"));
    644 +}
    645 +
    646 +void
    647 +delete_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer *user_data)
    648 +{
    649 +  GtkWidget *entry = GTK_WIDGET (user_data);
    650 +  gtk_entry_set_text (GTK_ENTRY (entry), "");
    651 +
    652 +  gtk_widget_hide (widget);
    653 +}
    654 +
    655 +static void 
    656 +cb_dialog_response (GtkWidget *widget, GladeXML *dialog)
    657 +{
    658 +	capplet_help (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
    659 +		      "user-guide.xml",
    660 +		      "goscustdesk-39");
    661 +}
    662 +
    663 +typedef struct 
    664 +{
    665 +  GtkFileSelection *fs;
    666 +  GladeXML *dialog;
    667 +} FileSelData;
    668 +
    669 +
    670 +static void 
    671 +command_selection_ok (FileSelData *fs_data)
    672 +{
    673 +  GtkWidget *action_tf = glade_xml_get_widget (fs_data->dialog, "action_tf");
    674 +  gchar **selections;
    675 +
    676 +  selections = gtk_file_selection_get_selections (fs_data->fs);
    677 +
    678 +  gtk_entry_set_text (GTK_ENTRY (action_tf), selections[0]);
    679 +  gtk_widget_destroy (GTK_WIDGET (fs_data->fs));
    680 +}
    681 +
    682 +static void 
    683 +set_command (GtkWidget *widget, GladeXML *dialog)
    684 +{
    685 +  GtkWidget *window;
    686 +  FileSelData *fs_data = g_new (FileSelData, 1);
    687 +  
    688 +  window = gtk_file_selection_new ("Select Command");
    689 +
    690 +  gtk_window_set_screen (GTK_WINDOW (window),
    691 +			 gtk_widget_get_screen (widget));
    692 +
    693 +  gtk_file_selection_set_select_multiple (GTK_FILE_SELECTION (window),
    694 +					  FALSE);
    695 +
    696 +  g_signal_connect (window, "destroy",
    697 +		    G_CALLBACK (gtk_widget_destroyed),
    698 +		    &window);
    699 + 
    700 +  fs_data->fs = GTK_FILE_SELECTION (window);
    701 +  fs_data->dialog = dialog;
    702 +  
    703 +  g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
    704 +			    "clicked",			    
    705 +			    G_CALLBACK (command_selection_ok),
    706 +			    fs_data);
    707 +
    708 +  g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
    709 +			    "clicked",
    710 +			    G_CALLBACK (gtk_widget_destroy),
    711 +			    window);
    712 +  gtk_widget_show (window);
    713 +}
    714 +
    715 +GladeXML *
    716 +setup_custom_binding_dialog ()
    717 +{
    718 +  static GladeXML *dialog = NULL;
    719 +  GtkWidget *widget, *entry;
    720 +
    721 +  if (dialog)
    722 +    return dialog;
    723 +
    724 +  /* setup dialog */
    725 +  dialog = glade_xml_new (GNOMECC_GLADE_DIR "/gnome-keybinding-properties.glade", "custom-binding-dialog", NULL);
    726 +  
    727 +  widget = WID ("custom-binding-dialog");
    728 +  entry = WID ("action_tf");
    729 +  g_signal_connect (G_OBJECT (widget), "delete_event",
    730 +		    G_CALLBACK (delete_event_cb),
    731 +		    entry);
    732 +
    733 +  g_signal_connect (G_OBJECT (WID ("browse_button")), "clicked", 
    734 +		    G_CALLBACK (set_command), dialog);
    735 +
    736 +  g_signal_connect (G_OBJECT (WID ("cancelbutton1")), "clicked", 
    737 +		    G_CALLBACK (custom_cancel), dialog);
    738 +
    739 +  g_signal_connect (G_OBJECT (WID ("okbutton1")), "clicked", 
    740 +		    G_CALLBACK (add_real_key), dialog);
    741 +  
    742 +  g_signal_connect (G_OBJECT (WID ("helpbutton2")), "clicked", 
    743 +		    G_CALLBACK (cb_dialog_response), NULL);
    744 +
    745 +  /* gtk_widget_hide (WID ("custom-binding-dialog")); */
    746 +  return dialog;
    747 +}
    748 +void 
    749 +edit_custom (GtkWidget *widget)
    750 +{
    751 +  KeyEntry *entry = find_keyentry_selected (GTK_TREE_VIEW (glade_xml_get_widget (main_dialog,"shortcut_treeview")));
    752 +  if (entry)
    753 +    {
    754 +      if (entry->custom_key)
    755 +	{
    756 +	  GladeXML *dialog = setup_custom_binding_dialog ();
    757 +	  GtkWidget *widget;
    758 +	  widget =  WID ("action_tf");
    759 +	  g_object_set_data (G_OBJECT (widget), "key_entry", entry);
    760 +	  gtk_entry_set_text (GTK_ENTRY (widget), entry->action);
    761 +	  gtk_widget_show_all (WID ("custom-binding-dialog"));
    762 +	}
    763 +    }
    764 +}
    765 +void 
    766 +add_custom (GtkWidget *widget) 
    767 +{
    768 +  GladeXML *dialog = setup_custom_binding_dialog ();
    769 +  GtkWidget *action_widget;
    770 +  action_widget =  WID ("action_tf");
    771 +  g_object_set_data (G_OBJECT (action_widget), "key_entry", NULL);
    772 +  gtk_widget_show_all (WID ("custom-binding-dialog"));
    773 +}
    774 +
    775 +void 
    776 +create_custom_bindings_list ()
    777 +{
    778 +  GConfClient *client;
    779 +  GSList *list, *li;
    780 +  int num_bindings = 0, i = 0;
    781 +  
    782 +  client  = gconf_client_get_default ();
    783 +
    784 +  list = gconf_client_all_dirs (client, GCONF_CUSTOM_BINDING_DIR, NULL);
    785 +
    786 +  num_bindings = g_slist_length (list);
    787 +
    788 +  if (custom_binding_list)
    789 +    g_free (custom_binding_list);
    790 +    
    791 +
    792 +  custom_binding_list = g_new0 (KeyListEntry, num_bindings+1);
    793 +
    794 +  for (li = list; li != NULL; li = li->next)
    795 +    {
    796 +      char *subdir = li->data;
    797 +      li->data = NULL;
    798 +      custom_binding_list[i].name = subdir;
    799 +      i++;
    800 +    }
    801 +  g_slist_free (list);
    802 +}
    803 +
    804 +KeyEntry *
    805 +custom_key_new (char *dir)
    806 +{
    807 +  GConfValue *value;
    808 +  KeyEntry *new_binding;
    809 +  GSList *tmp_elem = NULL, *list = NULL, *li;
    810 +  char *gconf_key;
    811 +  char *action = NULL;
    812 +  char *key = NULL;
    813 +  
    814 +  g_return_val_if_fail (dir != NULL, NULL);
    815 +  
    816 +  /* value = gconf_entry_get_value (entry); */
    817 +  gconf_key = dir;
    818 +
    819 +  if (!gconf_key)
    820 +    return NULL;
    821 +
    822 +  /* Get entries for this binding */
    823 +  list = gconf_client_all_entries (gconf_client_get_default (), dir, NULL);
    824 +
    825 +  for (li = list; li != NULL; li = li->next)
    826 +    {
    827 +      GConfEntry *entry = li->data;
    828 +      char *key_name = g_path_get_basename (gconf_entry_get_key (entry));
    829 +      if (strcmp (key_name, "action") == 0)
    830 +	{
    831 +	  if (!action)
    832 +	    {
    833 +	      value = gconf_entry_get_value (entry);
    834 +              if (value) 
    835 +               {
    836 +	          if (value->type != GCONF_VALUE_STRING)
    837 +		     return NULL;
    838 +	          action = g_strdup (gconf_value_get_string (value));
    839 +              }
    840 +	    }
    841 +	  else
    842 +	    /* SUN_BRANDING */
    843 +	    g_warning (_("Key Binding (%s) has its action defined multiple times\n"),
    844 +		       gconf_key);
    845 +	}
    846 +      if (strcmp (key_name, "binding") == 0)
    847 +	{
    848 +	  if (!key)
    849 +	    {
    850 +	      value = gconf_entry_get_value (entry);
    851 +              if (value)
    852 +                {
    853 +	          if (value->type != GCONF_VALUE_STRING)
    854 +		     return NULL;
    855 +	          key = g_strdup (gconf_value_get_string (value));
    856 +               }
    857 +	    }
    858 +	  else
    859 +	    /* SUN_BRANDING */
    860 +	    g_warning (_("Key Binding (%s) has its binding defined multiple times\n"),
    861 +		       gconf_key);
    862 +	}
    863 +    }
    864 +  if (!action || !key)
    865 +    { 
    866 +      /* SUN_BRANDING */
    867 +      g_warning (_("Key Binding (%s) is incomplete\n"), gconf_key);
    868 +      return NULL;
    869 +    }
    870 +  
    871 +  new_binding = g_new0 (KeyEntry, 1);
    872 +  
    873 +  
    874 +  new_binding->binding = key;
    875 +  new_binding->action = action;
    876 +  new_binding->gconf_key = gconf_key;
    877 +  return new_binding;
    878 +}
    879 +
    880 +gboolean
    881 +is_gconf_key_custom_binding (char *key)
    882 +{
    883 +  char *str = NULL;
    884 +
    885 +  str = g_strrstr (key, "keybindings");
    886 +
    887 +  if (str)
    888 +    return TRUE;
    889 +  return FALSE;
    890 +}
    891 +
    892 +void
    893 +cursor_changed_cb (GtkTreeView    *tree_view,
    894 +                   GladeXML       *dialog)
    895 +{
    896 +  KeyEntry *key_entry = find_keyentry_selected (tree_view);
    897 +  GtkWidget *widget;
    898 +
    899 +  my_verbose ("In cursor_changed_cb\n");
    900 +  if (key_entry)
    901 +    {
    902 +      if (key_entry->custom_key)
    903 +        {
    904 +          widget = WID ("edit_custom_button");
    905 +          gtk_widget_set_sensitive (widget, TRUE);
    906 +          widget = WID ("disable_custom_button");
    907 +          gtk_widget_set_sensitive (widget, TRUE);
    908 +        }
    909 +      else
    910 +        {
    911 +          widget = WID ("edit_custom_button");
    912 +          gtk_widget_set_sensitive (widget, FALSE);
    913 +          widget = WID ("disable_custom_button");
    914 +          gtk_widget_set_sensitive (widget, FALSE);
    915 +        }
    916 +    }
    917 +  else
    918 +    {
    919 +      widget = WID ("edit_custom_button");
    920 +      gtk_widget_set_sensitive (widget, FALSE);
    921 +      widget = WID ("disable_custom_button");
    922 +      gtk_widget_set_sensitive (widget, FALSE);
    923 +    }
    924 +}
    925 
    926 
    927 --- gnome-control-center-2.23.3/capplets/keybindings/custom-binding.h.orig	2008-06-05 10:47:09.696631562 +0100
    928 +++ gnome-control-center-2.23.3/capplets/keybindings/custom-binding.h	2008-06-05 10:47:34.138624596 +0100
    929 @@ -0,0 +1,120 @@
    930 +/* Erwann Chenede 2002 */
    931 +
    932 +#include <config.h>
    933 +
    934 +#include <string.h>
    935 +#include <gtk/gtk.h>
    936 +#include <gconf/gconf-client.h>
    937 +#include <gdk/gdkx.h>
    938 +#include <glade/glade.h>
    939 +#include <X11/Xatom.h>
    940 +
    941 +#include "wm-common.h"
    942 +#include "capplet-util.h"
    943 +#include "eggcellrendererkeys.h"
    944 +#include "activate-settings-daemon.h"
    945 +
    946 +#ifndef __CUSTOM_BINDING__H__
    947 +#define __CUSTOM_BINDING__H__
    948 +
    949 +#define GCONF_CUSTOM_BINDING_DIR "/desktop/gnome/keybindings"
    950 +
    951 +typedef enum {
    952 +  ALWAYS_VISIBLE,
    953 +  N_WORKSPACES_GT
    954 +} KeyListEntryVisibility;
    955 +
    956 +typedef enum {
    957 +  COMPARISON_NONE = 0,
    958 +  COMPARISON_GT,
    959 +  COMPARISON_LT,
    960 +  COMPARISON_EQ
    961 +} Comparison;
    962 +
    963 +typedef struct
    964 +{
    965 +  char *name;
    966 +  int value;
    967 +  char *key;
    968 +  char *description_name;
    969 +  Comparison comparison;
    970 +} KeyListEntry;
    971 +
    972 +enum
    973 +{
    974 +  DESCRIPTION_COLUMN,
    975 +  KEYENTRY_COLUMN,
    976 +  N_COLUMNS
    977 +};
    978 +
    979 +typedef struct
    980 +{
    981 +  char *gconf_key;
    982 +  guint keyval;
    983 +  guint keycode;
    984 +  EggVirtualModifierType mask;
    985 +  gboolean editable;
    986 +  GtkTreeModel *model;
    987 +  char *description;
    988 +  char *desc_gconf_key;
    989 +  gboolean desc_editable;
    990 +  guint gconf_cnxn;
    991 +  guint gconf_cnxn_desc;
    992 +  /* Custom Key Stuff */
    993 +  gboolean custom_key;
    994 +  guint cmd_line_cnxn;
    995 +  char *action;
    996 +  char *binding;
    997 +} KeyEntry;
    998 +
    999 +void
   1000 +my_verbose (const char *format, ...);
   1001 +
   1002 +void
   1003 +cmd_line_changed (GConfClient *client,
   1004 +		  guint        cnxn_id,
   1005 +		  GConfEntry  *entry,
   1006 +		  gpointer     user_data);
   1007 +
   1008 +void 
   1009 +disable_custom (GtkWidget *widget, GtkTreeView *tree_view);
   1010 +
   1011 +gboolean
   1012 +grab_key_callback (GtkWidget    *widget,
   1013 +                   GdkEventKey  *event,
   1014 +                   void         *data);
   1015 +void grab_key (GtkWidget *widget, GladeXML *dialog);
   1016 +
   1017 +void custom_cancel (GtkWidget *widget, GladeXML *dialog);
   1018 +
   1019 +void delete_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer *user_data);
   1020 +void cursor_changed_cb (GtkTreeView *treeview, GladeXML *dialog);
   1021 +
   1022 +GladeXML *
   1023 +setup_custom_binding_dialog ();
   1024 +
   1025 +void 
   1026 +add_custom (GtkWidget *widget);
   1027 +
   1028 +void 
   1029 +edit_custom (GtkWidget *widget);
   1030 +
   1031 +void 
   1032 +create_custom_bindings_list ();
   1033 +
   1034 +KeyEntry *
   1035 +custom_key_new (char *dir);
   1036 +
   1037 +gboolean
   1038 +is_gconf_key_custom_binding (char *key);
   1039 +
   1040 +gboolean
   1041 +keybinding_key_changed_foreach (GtkTreeModel *model,
   1042 +				GtkTreePath  *path,
   1043 +				GtkTreeIter  *iter,
   1044 +				gpointer      user_data);
   1045 +
   1046 +void
   1047 +reload_key_entries (gpointer wm_name, GladeXML *dialog);
   1048 +#endif /*__CUSTOM_BINDING__H__*/
   1049 +
   1050 
   1051 --- gnome-control-center-2.23.6.old/capplets/keybindings/gnome-keybinding-properties.c	2008-08-06 11:19:27.037712000 +0100
   1052 +++ gnome-control-center-2.23.6/capplets/keybindings/gnome-keybinding-properties.c	2008-08-06 11:22:50.489019000 +0100
   1053 @@ -15,6 +15,7 @@
   1054  #include "capplet-util.h"
   1055  #include "eggcellrendererkeys.h"
   1056  #include "activate-settings-daemon.h"
   1057 +#include "custom-binding.h"
   1058  
   1059  #define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
   1060  #define MAX_ELEMENTS_BEFORE_SCROLLING 10
   1061 @@ -29,29 +30,7 @@
   1062    GArray *entries;
   1063  } KeyList;
   1064  
   1065 -typedef enum {
   1066 -  COMPARISON_NONE = 0,
   1067 -  COMPARISON_GT,
   1068 -  COMPARISON_LT,
   1069 -  COMPARISON_EQ
   1070 -} Comparison;
   1071 -
   1072 -typedef struct
   1073 -{
   1074 -  char *name;
   1075 -  int value;
   1076 -  char *key;
   1077 -  char *description_name;
   1078 -  Comparison comparison;
   1079 -} KeyListEntry;
   1080 -
   1081 -enum
   1082 -{
   1083 -  DESCRIPTION_COLUMN,
   1084 -  KEYENTRY_COLUMN,
   1085 -  N_COLUMNS
   1086 -};
   1087 -
   1088 +/*
   1089  typedef struct
   1090  {
   1091    char *gconf_key;
   1092 @@ -66,14 +45,19 @@
   1093    guint gconf_cnxn;
   1094    guint gconf_cnxn_desc;
   1095  } KeyEntry;
   1096 +*/
   1097 +KeyListEntry *custom_binding_list = NULL;
   1098 +GladeXML *main_dialog;
   1099  
   1100  static gboolean block_accels = FALSE;
   1101  
   1102  static GladeXML *
   1103  create_dialog (void)
   1104  {
   1105 -  return glade_xml_new (GNOMECC_GLADE_DIR "/gnome-keybinding-properties.glade",
   1106 +  main_dialog = glade_xml_new (GNOMECC_GLADE_DIR "/gnome-keybinding-properties.glade",
   1107                          "gnome-keybinding-dialog", NULL);
   1108 +
   1109 +  return main_dialog;
   1110  }
   1111  
   1112  static char*
   1113 @@ -172,7 +156,7 @@
   1114  		  NULL);
   1115  }
   1116  
   1117 -static gboolean
   1118 +gboolean
   1119  keybinding_key_changed_foreach (GtkTreeModel *model,
   1120  				GtkTreePath  *path,
   1121  				GtkTreeIter  *iter,
   1122 @@ -188,6 +172,11 @@
   1123  
   1124    if (key_entry == tmp_key_entry)
   1125      {
   1126 +      if (key_entry->custom_key)
   1127 +        gtk_tree_store_set (GTK_TREE_STORE (key_entry->model), iter,
   1128 +                            DESCRIPTION_COLUMN, key_entry->action,
   1129 +                            -1);
   1130 +
   1131        gtk_tree_model_row_changed (key_entry->model, path, iter);
   1132        return TRUE;
   1133      }
   1134 @@ -338,6 +327,8 @@
   1135  
   1136            if (key_entry != NULL)
   1137              {
   1138 +              if (key_entry->custom_key == TRUE)
   1139 +                gconf_client_notify_remove (client, key_entry->cmd_line_cnxn);
   1140                gconf_client_remove_dir (client, key_entry->gconf_key, NULL);
   1141                gconf_client_notify_remove (client, key_entry->gconf_cnxn);
   1142                if (key_entry->gconf_cnxn_desc != 0)
   1143 @@ -422,7 +413,8 @@
   1144  static void
   1145  append_keys_to_tree (GladeXML           *dialog,
   1146  		     const gchar        *title,
   1147 -		     const KeyListEntry *keys_list)
   1148 +		     const KeyListEntry *keys_list,
   1149 +                     gboolean            custom_binding)
   1150  {
   1151    GConfClient *client;
   1152    GtkTreeIter parent_iter, iter;
   1153 @@ -472,75 +464,121 @@
   1154  
   1155    for (j = 0; keys_list[j].name != NULL; j++)
   1156      {
   1157 -      GConfEntry *entry;
   1158 -      KeyEntry *key_entry;
   1159 +      GConfEntry *entry = NULL;
   1160 +      KeyEntry *key_entry = NULL;
   1161        const gchar *key_string;
   1162        gchar *key_value;
   1163        gchar *description;
   1164  
   1165        if (!should_show_key (&keys_list[j]))
   1166 -	continue;
   1167 -
   1168 -      key_string = keys_list[j].name;
   1169 +        continue;
   1170  
   1171 -      entry = gconf_client_get_entry (client,
   1172 -                                      key_string,
   1173 -				      NULL,
   1174 -				      TRUE,
   1175 -				      NULL);
   1176 -      if (entry == NULL)
   1177 -	{
   1178 -	  /* We don't actually want to popup a dialog - just skip this one */
   1179 -	  continue;
   1180 -	}
   1181 -
   1182 -      if (keys_list[j].description_name != NULL)
   1183 -        {
   1184 -          description = gconf_client_get_string (client, keys_list[j].description_name, NULL);
   1185 -        }
   1186 -      else
   1187 -        {
   1188 -          description = NULL;
   1189 +      if ( !custom_binding ) 
   1190 +       {
   1191 +        key_string = keys_list[j].name;
   1192 +
   1193 +        entry = gconf_client_get_entry (client,
   1194 +                                        key_string,
   1195 +                                        NULL,
   1196 +                                        TRUE,
   1197 +                                        NULL);
   1198 +       }
   1199 +      else if (entry == NULL)
   1200 +       {
   1201 +          key_entry = custom_key_new ((char *)keys_list[j].name);
   1202 +          if (!key_entry)
   1203 +            continue;
   1204 +          key_string = key_entry->gconf_key;
   1205 +       }
   1206 +
   1207 +
   1208 +      if (!custom_binding)
   1209 +       {
   1210 +        if (entry == NULL)
   1211 +          {
   1212 +            /* We don't actually want to popup a dialog - just skip this one */
   1213 +            continue;
   1214 +          }
   1215  
   1216 -          if (gconf_entry_get_schema_name (entry))
   1217 -            {
   1218 -              GConfSchema *schema;
   1219 +        if (keys_list[j].description_name != NULL)
   1220 +          {
   1221 +            description = gconf_client_get_string (client, keys_list[j].description_name, NULL);
   1222 +          }
   1223 +        else
   1224 +          {
   1225 +            description = NULL;
   1226  
   1227 -              schema = gconf_client_get_schema (client,
   1228 -                                                gconf_entry_get_schema_name (entry),
   1229 -                                                NULL);
   1230 -              if (schema != NULL)
   1231 -                {
   1232 -                  description = g_strdup (gconf_schema_get_short_desc (schema));
   1233 -                  gconf_schema_free (schema);
   1234 -                }
   1235 -            }
   1236 -        }
   1237 +            if (gconf_entry_get_schema_name (entry))
   1238 +              {
   1239 +                GConfSchema *schema;
   1240 +
   1241 +                schema = gconf_client_get_schema (client,
   1242 +                                                  gconf_entry_get_schema_name (entry),
   1243 +                                                  NULL);
   1244 +                if (schema != NULL)
   1245 +                  {
   1246 +                    description = g_strdup (gconf_schema_get_short_desc (schema));
   1247 +                    gconf_schema_free (schema);
   1248 +                  }
   1249 +              }
   1250 +          }
   1251 +       }
   1252  
   1253 -      key_entry = g_new0 (KeyEntry, 1);
   1254 -      key_entry->gconf_key = g_strdup (key_string);
   1255 -      key_entry->editable = gconf_entry_get_is_writable (entry);
   1256 -      key_entry->model = model;
   1257 -      key_entry->description = description;
   1258 -      if (keys_list[j].description_name != NULL)
   1259 +      if (!custom_binding)
   1260 +      {
   1261 +        key_entry = g_new0 (KeyEntry, 1);
   1262 +        key_entry->gconf_key = g_strdup (key_string);
   1263 +        key_entry->editable = gconf_entry_get_is_writable (entry);
   1264 +        key_entry->model = model;
   1265 +        key_entry->description = description;
   1266 +        if (keys_list[j].description_name != NULL)
   1267          {
   1268            key_entry->desc_gconf_key =  g_strdup (keys_list[j].description_name);
   1269 -          key_entry->desc_editable = gconf_client_key_is_writable (client, key_entry->desc_gconf_key, NULL);
   1270 +          key_entry->desc_editable = gconf_client_key_is_writable (client,
   1271 +                                            key_entry->desc_gconf_key, NULL);
   1272            key_entry->gconf_cnxn_desc = gconf_client_notify_add (client,
   1273 -								key_entry->desc_gconf_key,
   1274 -								(GConfClientNotifyFunc) &keybinding_description_changed,
   1275 -								key_entry, NULL, NULL);
   1276 +                        key_entry->desc_gconf_key,
   1277 +                        (GConfClientNotifyFunc) &keybinding_description_changed,
   1278 +                        key_entry, NULL, NULL);
   1279          }
   1280  
   1281 -      gconf_client_add_dir (client, key_string, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1282 -      key_entry->gconf_cnxn = gconf_client_notify_add (client,
   1283 -						       key_string,
   1284 -						       (GConfClientNotifyFunc) &keybinding_key_changed,
   1285 -						       key_entry, NULL, NULL);
   1286 -
   1287 -      key_value = gconf_client_get_string (client, key_string, NULL);
   1288 -      binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
   1289 -      g_free (key_value);
   1290 +        gconf_client_add_dir (client, key_string, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1291 +        key_entry->gconf_cnxn = gconf_client_notify_add (client,
   1292 +                                                         key_string,
   1293 +                                                         (GConfClientNotifyFunc) &keybinding_key_changed,
   1294 +                                                         key_entry, NULL, NULL);
   1295 +
   1296 +        key_value = gconf_client_get_string (client, key_string, NULL);
   1297 +        binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
   1298 +        g_free (key_value);
   1299 +      }
   1300 +      else 
   1301 +      {
   1302 +        char *key_binding =
   1303 +                g_strdup_printf ("%s/binding", key_entry->gconf_key);
   1304 +        char *cmd_binding = g_strdup_printf ("%s/action", key_entry->gconf_key);
   1305 +        key_entry->editable = TRUE;
   1306 +        key_entry->model = model;
   1307 +        gconf_client_add_dir (client, key_entry->gconf_key,
   1308 +                              GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1309 +
   1310 +        key_entry->gconf_cnxn =
   1311 +                gconf_client_notify_add (client,
   1312 +                                key_binding,
   1313 +                                (GConfClientNotifyFunc) &keybinding_key_changed,
   1314 +                                key_entry, NULL, NULL);
   1315 +        binding_from_string (key_entry->binding, &key_entry->keyval,
   1316 +                             &key_entry->keycode, &key_entry->mask);
   1317 +
   1318 +        key_entry->custom_key = TRUE;
   1319 +        key_entry->cmd_line_cnxn = gconf_client_notify_add (client, cmd_binding,
   1320 +                                      (GConfClientNotifyFunc) &cmd_line_changed,
   1321 +                                      key_entry, NULL, NULL);
   1322 +        key_entry->action = g_strdup (gconf_client_get_string (client,
   1323 +                                      cmd_binding, NULL ));
   1324 +        g_free (key_binding);
   1325 +        g_free (cmd_binding);
   1326 +      }
   1327  
   1328        gconf_entry_free (entry);
   1329        ensure_scrollbar (dialog, i);
   1330 @@ -548,9 +586,22 @@
   1331        ++i;
   1332        gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent_iter);
   1333        /* we use the DESCRIPTION_COLUMN only for the section headers */
   1334 -      gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
   1335 -			  KEYENTRY_COLUMN, key_entry,
   1336 -			  -1);
   1337 +
   1338 +      if (!custom_binding)
   1339 +      {
   1340 +        /* we use the DESCRIPTION_COLUMN only for the section headers */
   1341 +        gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
   1342 +                            KEYENTRY_COLUMN, key_entry,
   1343 +                            -1);
   1344 +      }
   1345 +      else 
   1346 +      {
   1347 +         gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
   1348 +                             DESCRIPTION_COLUMN, key_entry->action,
   1349 +                             KEYENTRY_COLUMN, key_entry,
   1350 +                             -1);
   1351 +      }
   1352 +
   1353        gtk_tree_view_expand_all (GTK_TREE_VIEW (WID ("shortcut_treeview")));
   1354      }
   1355  
   1356 @@ -751,7 +802,7 @@
   1357        title = _(keylist->name);
   1358      }
   1359  
   1360 -  append_keys_to_tree (dialog, title, keys);
   1361 +  append_keys_to_tree (dialog, title, keys, FALSE);
   1362  
   1363    g_free (keylist->name);
   1364    g_free (keylist->package);
   1365 @@ -801,7 +852,7 @@
   1366        g_array_append_val (entries, key);
   1367  
   1368        keys = (KeyListEntry *) entries->data;
   1369 -      append_keys_to_tree (dialog, _("Custom Shortcuts"), keys);
   1370 +      append_keys_to_tree (dialog, _("Custom Shortcuts"), keys, FALSE);
   1371        for (i = 0; i < entries->len; ++i)
   1372          {
   1373            g_free (keys[i].name);
   1374 @@ -812,7 +863,7 @@
   1375    g_array_free (entries, TRUE);
   1376  }
   1377  
   1378 -static void
   1379 +void
   1380  reload_key_entries (gpointer wm_name, GladeXML *dialog)
   1381  {
   1382    GDir *dir;
   1383 @@ -848,6 +899,10 @@
   1384    g_list_free (list);
   1385  
   1386    append_keys_to_tree_from_gconf (dialog, GCONF_BINDING_DIR);
   1387 +
   1388 +  /* SUN_BRANDING */
   1389 +  append_keys_to_tree (dialog, _("Custom Shortcuts"), custom_binding_list,
   1390 +                       TRUE);
   1391  }
   1392  
   1393  static void
   1394 @@ -1120,10 +1175,22 @@
   1395    str = binding_name (keyval, keycode, mask, FALSE);
   1396  
   1397    client = gconf_client_get_default ();
   1398 -  gconf_client_set_string (client,
   1399 -                           key_entry->gconf_key,
   1400 -                           str,
   1401 -                           &err);
   1402 +
   1403 +  if (!key_entry->custom_key)
   1404 +    gconf_client_set_string (client,
   1405 +                             key_entry->gconf_key,
   1406 +                             str,
   1407 +                             &err);
   1408 +  else
   1409 +  {
   1410 +    char *key = g_strdup_printf ("%s/binding", key_entry->gconf_key);
   1411 +    gconf_client_set_string (client,
   1412 +                             key,
   1413 +                             str,
   1414 +                             &err);
   1415 +    g_free (key);
   1416 +  }
   1417 +
   1418    g_free (str);
   1419    g_object_unref (client);
   1420  
   1421 @@ -1163,9 +1230,25 @@
   1422  
   1423    /* Unset the key */
   1424    client = gconf_client_get_default();
   1425 +
   1426 +  if (!key_entry->custom_key) {
   1427 +      gconf_client_set_string (gconf_client_get_default(),
   1428 +                             key_entry->gconf_key,
   1429 +                             "disabled",
   1430 +                             &err);
   1431 +  } else {
   1432 +    char *key = g_strdup_printf ("%s/binding", key_entry->gconf_key);
   1433 +    gconf_client_set_string (gconf_client_get_default(),
   1434 +                             key,
   1435 +                             "disabled",
   1436 +                             &err);
   1437 +    g_free (key);
   1438 +
   1439 +  }
   1440 +
   1441    gconf_client_set_string (client,
   1442  			   key_entry->gconf_key,
   1443 -			   "",
   1444 +			   "disabled",
   1445  			   &err);
   1446    g_object_unref (client);
   1447  
   1448 @@ -1348,10 +1431,10 @@
   1449  
   1450    client = gconf_client_get_default ();
   1451  
   1452 -  g_signal_connect (treeview, "button_press_event",
   1453 -		    G_CALLBACK (start_editing_cb), NULL);
   1454    g_signal_connect (treeview, "row-activated",
   1455  		    G_CALLBACK (start_editing_kb_cb), NULL);
   1456 +  g_signal_connect (treeview, "cursor-changed",
   1457 +                    G_CALLBACK (cursor_changed_cb), dialog);
   1458  
   1459    renderer = gtk_cell_renderer_text_new ();
   1460  
   1461 @@ -1390,12 +1473,15 @@
   1462  
   1463    gconf_client_add_dir (client, GCONF_BINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1464    gconf_client_add_dir (client, "/apps/metacity/general", GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1465 +  gconf_client_add_dir (client, GCONF_CUSTOM_BINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
   1466    gconf_client_notify_add (client,
   1467  			   "/apps/metacity/general/num_workspaces",
   1468  			   (GConfClientNotifyFunc) key_entry_controlling_key_changed,
   1469  			   dialog, NULL, NULL);
   1470    g_object_unref (client);
   1471  
   1472 +  create_custom_bindings_list ();
   1473 +
   1474    /* set up the dialog */
   1475    wm_name = wm_common_get_current_window_manager();
   1476    reload_key_entries (wm_name, dialog);
   1477 @@ -1407,6 +1493,19 @@
   1478  
   1479    g_signal_connect (widget, "key_press_event", G_CALLBACK (maybe_block_accels), NULL);
   1480    g_signal_connect (widget, "response", G_CALLBACK (cb_dialog_response), dialog);
   1481 +
   1482 +  /* set up custom bindings buttons and dialog*/
   1483 +  widget = WID ("disable_custom_button");
   1484 +  g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (disable_custom),
   1485 +                    GTK_TREE_VIEW (WID ("shortcut_treeview")));
   1486 +  gtk_widget_set_sensitive (widget, FALSE);
   1487 +
   1488 +  widget = WID ("add_custom_button");
   1489 +  g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (add_custom), NULL);
   1490 +
   1491 +  widget = WID ("edit_custom_button");
   1492 +  g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (edit_custom), NULL);
   1493 +  gtk_widget_set_sensitive (widget, FALSE);
   1494  }
   1495  
   1496  int
   1497