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