summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>2001-11-13 00:53:47 +0000
committerTim Janik <timj@src.gnome.org>2001-11-13 00:53:47 +0000
commitd07573c090f8ca8c3fdb8f4d3f63b32be96ea7d6 (patch)
treeea660dfa3bec08f14714db1b2e9699bf5f126394
parentaebe24f2bba1a41b23ab62b7adfc867e28adb3fc (diff)
downloadgtk+-d07573c090f8ca8c3fdb8f4d3f63b32be96ea7d6.tar.gz
added gtkaccelmap.sgml. other updates.
Mon Nov 12 23:06:38 2001 Tim Janik <timj@gtk.org> * added gtkaccelmap.sgml. other updates. Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org> * gtk/maketypes.awk: fix type utils generation on unix. * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator registry. * gtk/gtkaccelgroup.[hc]: major API/implementation revamp: removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default, gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry, gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove, gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object. introduced ::accel_changed signal for change notification, and gtk_accel_group_connect/disconnect to connect closures to accel groups. made gtk_accel_group_attach/detach and gtk_accel_group_activate private functions. deprecated gtk_accel_group_ref/unref. * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention to accel group changed notification and basically operate on closures. removed gtk_accel_label_get_accel_object and gtk_accel_label_set_accel_object. introduced gtk_accel_label_set_accel_closure, and for convenience, gtk_accel_label_set_accel_widget. * gtk/gtkitemfactory.[hc]: removed accelerator propagation code which mostly moved into gtkaccelmap.[hc]. removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_* and gtk_item_factory_print_func. * gtk/gtkmain.c: call _gtk_accel_map_init(). * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(), that associates an accelerator path with menu items, through which persistent accelerator settings on menu items are enabled. * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator paths of menu item can be default constructed to allow installation of accelerators on menu items that don't come with an accelerator binding by default. * gtk/gtksettings.c: fix STRING type rc settings by special casing them appropriately in the parser. * gtk/gtksignal.[hc]: allow a class function offset of 0 for gtk_signal_newv(). * gtk/gtkwidget.[hc]: accelerator API revamp. removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal, gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and gtk_widget_(un)lock_accelerators. accelerators maintained through gtk_widget_add/remove_accelerator() are not runtime changable now, the correct sequence to setup a widget for runtime changable accelerators is now: gtk_accel_map_add_entry(accel_path, key, mods); _gtk_widget_set_accel_path(widget, accel_path, accel_group); * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel group changes (as well as mnemonic changes) through the new signal ::accels_changed. Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org> * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle GString->string conversions.
-rw-r--r--ChangeLog66
-rw-r--r--ChangeLog.pre-2-066
-rw-r--r--ChangeLog.pre-2-1066
-rw-r--r--ChangeLog.pre-2-266
-rw-r--r--ChangeLog.pre-2-466
-rw-r--r--ChangeLog.pre-2-666
-rw-r--r--ChangeLog.pre-2-866
-rw-r--r--demos/gtk-demo/appwindow.c4
-rw-r--r--demos/gtk-demo/item_factory.c2
-rw-r--r--demos/gtk-demo/menus.c5
-rw-r--r--docs/reference/ChangeLog4
-rw-r--r--docs/reference/gtk/gtk-docs.sgml6
-rw-r--r--docs/reference/gtk/gtk-sections.txt91
-rw-r--r--docs/reference/gtk/tmpl/gtk-unused.sgml251
-rw-r--r--docs/reference/gtk/tmpl/gtkaccelgroup.sgml78
-rw-r--r--docs/reference/gtk/tmpl/gtkaccellabel.sgml28
-rw-r--r--docs/reference/gtk/tmpl/gtkcolorsel.sgml6
-rw-r--r--docs/reference/gtk/tmpl/gtkcombo.sgml2
-rw-r--r--docs/reference/gtk/tmpl/gtkdialog.sgml2
-rw-r--r--docs/reference/gtk/tmpl/gtkenums.sgml1
-rw-r--r--docs/reference/gtk/tmpl/gtkitemfactory.sgml59
-rw-r--r--docs/reference/gtk/tmpl/gtkmenu.sgml18
-rw-r--r--docs/reference/gtk/tmpl/gtkmenuitem.sgml9
-rw-r--r--docs/reference/gtk/tmpl/gtkpaned.sgml3
-rw-r--r--docs/reference/gtk/tmpl/gtktoolbar.sgml4
-rw-r--r--docs/reference/gtk/tmpl/gtktreednd.sgml1
-rw-r--r--docs/reference/gtk/tmpl/gtktreeview.sgml52
-rw-r--r--docs/reference/gtk/tmpl/gtkwidget.sgml63
-rw-r--r--docs/reference/gtk/tmpl/gtkwindow.sgml7
-rw-r--r--gtk/Makefile.am2
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkaccelgroup.c1193
-rw-r--r--gtk/gtkaccelgroup.h183
-rw-r--r--gtk/gtkaccellabel.c371
-rw-r--r--gtk/gtkaccellabel.h29
-rw-r--r--gtk/gtkaccelmap.c858
-rw-r--r--gtk/gtkaccelmap.h81
-rw-r--r--gtk/gtkitemfactory.c581
-rw-r--r--gtk/gtkitemfactory.h26
-rw-r--r--gtk/gtkmain.c3
-rw-r--r--gtk/gtkmarshal.list5
-rw-r--r--gtk/gtkmarshalers.list5
-rw-r--r--gtk/gtkmenu.c202
-rw-r--r--gtk/gtkmenu.h6
-rw-r--r--gtk/gtkmenuitem.c138
-rw-r--r--gtk/gtkmenuitem.h9
-rw-r--r--gtk/gtknotebook.c1
-rw-r--r--gtk/gtksettings.c24
-rw-r--r--gtk/gtksignal.c2
-rw-r--r--gtk/gtkwidget.c379
-rw-r--r--gtk/gtkwidget.h29
-rw-r--r--gtk/gtkwindow.c164
-rw-r--r--gtk/gtkwindow.h8
-rw-r--r--gtk/maketypes.awk6
-rw-r--r--tests/testgtk.c9
-rw-r--r--tests/testgtkrc3
56 files changed, 3349 insertions, 2127 deletions
diff --git a/ChangeLog b/ChangeLog
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 51ac8c00f9..31c26db01a 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,69 @@
+Mon Nov 12 23:08:37 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/maketypes.awk: fix type utils generation on unix.
+
+ * gtk/gtkaccelmap.[hc]: new files, implementing a global accelerator
+ registry.
+
+ * gtk/gtkaccelgroup.[hc]: major API/implementation revamp:
+ removed GTK_ACCEL_SIGNAL_VISIBLE, gtk_accel_group_get_default,
+ gtk_accel_group_get_entry, gtk_accel_group_(un)lock_entry,
+ gtk_accel_group_add/remove, gtk_accel_group_handle_add/remove,
+ gtk_accel_group_create_add/remove, gtk_accel_group_entries_from_object.
+ introduced ::accel_changed signal for change notification, and
+ gtk_accel_group_connect/disconnect to connect closures to accel groups.
+ made gtk_accel_group_attach/detach and gtk_accel_group_activate private
+ functions.
+ deprecated gtk_accel_group_ref/unref.
+
+ * gtk/gtkaccellabel.[hc]: changes to make accellabels pay attention
+ to accel group changed notification and basically operate on closures.
+ removed gtk_accel_label_get_accel_object and
+ gtk_accel_label_set_accel_object.
+ introduced gtk_accel_label_set_accel_closure, and for convenience,
+ gtk_accel_label_set_accel_widget.
+
+ * gtk/gtkitemfactory.[hc]: removed accelerator propagation code
+ which mostly moved into gtkaccelmap.[hc].
+ removed gtk_item_factory_parse_rc*, gtk_item_factory_dump_*
+ and gtk_item_factory_print_func.
+
+ * gtk/gtkmain.c: call _gtk_accel_map_init().
+
+ * gtk/gtkmenuitem.[hc]: introduced gtk_menu_item_set_accel_path(),
+ that associates an accelerator path with menu items, through which
+ persistent accelerator settings on menu items are enabled.
+
+ * gtk/gtkmenu.[hc]: added gtk_menu_set_accel_path() so accelerator
+ paths of menu item can be default constructed to allow installation
+ of accelerators on menu items that don't come with an accelerator
+ binding by default.
+
+ * gtk/gtksettings.c: fix STRING type rc settings by special casing
+ them appropriately in the parser.
+
+ * gtk/gtksignal.[hc]: allow a class function offset of 0 for
+ gtk_signal_newv().
+
+ * gtk/gtkwidget.[hc]: accelerator API revamp.
+ removed ::accelerator_add/remove signals, gtk_widget_accelerator_signal,
+ gtk_widget_accelerators_locked, gtk_widget_remove_accelerators and
+ gtk_widget_(un)lock_accelerators.
+ accelerators maintained through gtk_widget_add/remove_accelerator()
+ are not runtime changable now, the correct sequence to setup a
+ widget for runtime changable accelerators is now:
+ gtk_accel_map_add_entry(accel_path, key, mods);
+ _gtk_widget_set_accel_path(widget, accel_path, accel_group);
+
+ * gtk/gtkwindow.[hc]: accelerator changes, proxy and coalesce accel
+ group changes (as well as mnemonic changes) through the new signal
+ ::accels_changed.
+
+Sat Nov 10 12:08:56 2001 Tim Janik <timj@gtk.org>
+
+ * gtk/gtksettings.c (_gtk_settings_parse_convert): properly handle
+ GString->string conversions.
+
Mon Nov 12 19:33:52 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtkmessagedialog.c (gtk_message_dialog_new): Warn
diff --git a/demos/gtk-demo/appwindow.c b/demos/gtk-demo/appwindow.c
index c052bcbc60..5020152ff5 100644
--- a/demos/gtk-demo/appwindow.c
+++ b/demos/gtk-demo/appwindow.c
@@ -213,8 +213,8 @@ do_appwindow (void)
*/
accel_group = gtk_accel_group_new ();
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
- gtk_accel_group_unref (accel_group);
+ gtk_window_add_accel_group (window, accel_group);
+ g_object_unref (accel_group);
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
diff --git a/demos/gtk-demo/item_factory.c b/demos/gtk-demo/item_factory.c
index 34f3cb51d6..390f4a75c3 100644
--- a/demos/gtk-demo/item_factory.c
+++ b/demos/gtk-demo/item_factory.c
@@ -68,7 +68,7 @@ do_item_factory (void)
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
g_object_set_data_full (G_OBJECT (window), "<main>",
item_factory, (GDestroyNotify) g_object_unref);
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ gtk_window_add_accel_group (window, accel_group);
gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
diff --git a/demos/gtk-demo/menus.c b/demos/gtk-demo/menus.c
index 99899a7d32..60e20e1355 100644
--- a/demos/gtk-demo/menus.c
+++ b/demos/gtk-demo/menus.c
@@ -98,7 +98,7 @@ do_menus (void)
G_CALLBACK (gtk_true), NULL);
accel_group = gtk_accel_group_new ();
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ gtk_window_add_accel_group (window, accel_group);
gtk_window_set_title (GTK_WINDOW (window), "menus");
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
@@ -150,7 +150,7 @@ do_menus (void)
accel_group,
GDK_F1,
0,
- GTK_ACCEL_VISIBLE | GTK_ACCEL_SIGNAL_VISIBLE);
+ GTK_ACCEL_VISIBLE);
menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
@@ -175,7 +175,6 @@ do_menus (void)
GDK_F3,
0,
GTK_ACCEL_VISIBLE);
- gtk_widget_lock_accelerators (menuitem);
optionmenu = gtk_option_menu_new ();
gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog
index 963916c9c6..6a8b1c5138 100644
--- a/docs/reference/ChangeLog
+++ b/docs/reference/ChangeLog
@@ -1,3 +1,7 @@
+Mon Nov 12 23:06:38 2001 Tim Janik <timj@gtk.org>
+
+ * added gtkaccelmap.sgml. other updates.
+
2001-11-11 Matthias Clasen <matthiasc@poet.de>
* gdk-pixbuf/gdk-pixbuf-rendering.sgml,
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index fd0c2acdb8..50ee7a9bee 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -126,7 +126,8 @@
<!entity gtk-Styles SYSTEM "sgml/gtkstyle.sgml">
<!entity gtk-Themes SYSTEM "sgml/gtkthemes.sgml">
<!entity gtk-Resource-Files SYSTEM "sgml/gtkrc.sgml">
-<!entity gtk-Keyboard-Accelerators SYSTEM "sgml/gtkaccelgroup.sgml">
+<!entity GtkAccelGroup SYSTEM "sgml/gtkaccelgroup.sgml">
+<!entity gtk-accel-map SYSTEM "sgml/gtkaccelmap.sgml">
<!entity gtk-Selections SYSTEM "sgml/gtkselection.sgml">
<!entity gtk-Clipboards SYSTEM "sgml/gtkclipboard.sgml">
<!entity gtk-Drag-and-Drop SYSTEM "sgml/gtkdnd.sgml">
@@ -248,7 +249,8 @@ that is, GUI components such as #GtkButton or #GtkTextView.
<title>GTK+ Core Reference</title>
&gtk-General;
- &gtk-Keyboard-Accelerators;
+ &GtkAccelGroup;
+ &gtk-accel-map;
&gtk-Clipboards;
&gtk-Drag-and-Drop;
&gtk-Stock-Items;
diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt
index 37dbea2ecb..e184fd744f 100644
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@ -2,6 +2,52 @@
<INCLUDE>gtk/gtk.h</INCLUDE>
<SECTION>
+<FILE>gtkaccelgroup</FILE>
+<TITLE>Keyboard Accelerators</TITLE>
+GtkAccelGroup
+gtk_accel_group_get_type
+gtk_accel_group_new
+gtk_accel_group_connect
+gtk_accel_group_disconnect
+gtk_accel_group_query
+gtk_accel_group_activate
+gtk_accel_groups_activate
+gtk_accel_group_lock
+gtk_accel_group_unlock
+gtk_accelerator_valid
+gtk_accelerator_parse
+gtk_accelerator_name
+gtk_accelerator_set_default_mod_mask
+gtk_accelerator_get_default_mod_mask
+<SUBSECTION Private>
+<SUBSECTION Standard>
+GtkAccelGroupClass
+GTK_TYPE_ACCEL_GROUP
+GTK_ACCEL_GROUP
+GTK_IS_ACCEL_GROUP
+GTK_ACCEL_GROUP_CLASS
+GTK_IS_ACCEL_GROUP_CLASS
+GTK_ACCEL_GROUP_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gtkaccelmap</FILE>
+<TITLE>Accelerator Maps</TITLE>
+GtkAccelMapNotify
+GtkAccelMapForeach
+gtk_accel_map_add_entry
+gtk_accel_map_lookup_entry
+gtk_accel_map_change_entry
+gtk_accel_map_add_notifer
+gtk_accel_map_remove_notifer
+gtk_accel_map_load
+gtk_accel_map_save
+gtk_accel_map_foreach
+gtk_accel_map_load_fd
+gtk_accel_map_save_fd
+</SECTION>
+
+<SECTION>
<FILE>gtkaccellabel</FILE>
<TITLE>GtkAccelLabel</TITLE>
GtkAccelLabel
@@ -1428,6 +1474,7 @@ gtk_menu_reorder_child
gtk_menu_popup
gtk_menu_set_accel_group
gtk_menu_get_accel_group
+gtk_menu_set_accel_path
gtk_menu_set_title
gtk_menu_get_tearoff_state
gtk_menu_get_title
@@ -1481,6 +1528,7 @@ gtk_menu_item_new_with_label
gtk_menu_item_new_with_mnemonic
gtk_menu_item_set_right_justified
gtk_menu_item_set_submenu
+gtk_menu_item_set_accel_path
gtk_menu_item_remove_submenu
gtk_menu_item_select
gtk_menu_item_deselect
@@ -3881,49 +3929,6 @@ GtkRcContext
</SECTION>
<SECTION>
-<FILE>gtkaccelgroup</FILE>
-<TITLE>Keyboard Accelerators</TITLE>
-GtkAccelGroup
-gtk_accel_group_new
-gtk_accel_group_get_default
-gtk_accel_group_ref
-gtk_accel_group_unref
-gtk_accel_group_activate
-gtk_accel_groups_activate
-gtk_accel_group_attach
-gtk_accel_group_detach
-gtk_accel_group_add
-gtk_accel_group_remove
-gtk_accel_group_lock
-gtk_accel_group_unlock
-gtk_accelerator_valid
-gtk_accelerator_parse
-gtk_accelerator_name
-gtk_accelerator_set_default_mod_mask
-gtk_accelerator_get_default_mod_mask
-<SUBSECTION Private>
-GtkAccelEntry
-gtk_accel_group_get_type
-gtk_accel_group_get_entry
-gtk_accel_group_lock_entry
-gtk_accel_group_unlock_entry
-gtk_accel_group_handle_add
-gtk_accel_group_handle_remove
-gtk_accel_group_create_add
-gtk_accel_group_create_remove
-gtk_accel_groups_from_object
-gtk_accel_group_entries_from_object
-<SUBSECTION Standard>
-GtkAccelGroupClass
-GTK_ACCEL_GROUP
-GTK_TYPE_ACCEL_GROUP
-GTK_ACCEL_GROUP_CLASS
-GTK_ACCEL_GROUP_GET_CLASS
-GTK_IS_ACCEL_GROUP
-GTK_IS_ACCEL_GROUP_CLASS
-</SECTION>
-
-<SECTION>
<FILE>gtkselection</FILE>
<TITLE>Selections</TITLE>
GtkTargetEntry
diff --git a/docs/reference/gtk/tmpl/gtk-unused.sgml b/docs/reference/gtk/tmpl/gtk-unused.sgml
index 91412b12e8..86e08b9c73 100644
--- a/docs/reference/gtk/tmpl/gtk-unused.sgml
+++ b/docs/reference/gtk/tmpl/gtk-unused.sgml
@@ -495,9 +495,9 @@ This is a private struct used by GTK+ internally, don't worry about it.
@object:
@signal_id:
-<!-- ##### ARG GtkAccelLabel:accel-widget ##### -->
+<!-- ##### ARG GtkAccelLabel:accel-object ##### -->
<para>
-The widget whose accelerators are to be shown by the #GtkAccelLabel.
+
</para>
@@ -1186,6 +1186,29 @@ produce superscript and subscript.
@parent:
@priv:
+<!-- ##### USER_FUNCTION GtkTreeViewDraggableFunc ##### -->
+<para>
+
+</para>
+
+@tree_view:
+@context:
+@path:
+@user_data:
+@Returns:
+
+<!-- ##### USER_FUNCTION GtkTreeViewDroppableFunc ##### -->
+<para>
+
+</para>
+
+@tree_view:
+@context:
+@path:
+@pos:
+@user_data:
+@Returns:
+
<!-- ##### ARG GtkVScale:adjustment ##### -->
<para>
the #GtkAdjustment which sets the range of the scale.
@@ -1207,6 +1230,18 @@ the #GtkAdjustment which sets the range of the scale.
@arg1:
@Returns:
+<!-- ##### SIGNAL GtkWidget::add-accelerator ##### -->
+<para>
+
+</para>
+
+@widget: the object which received the signal.
+@accel_signal_id:
+@accel_group:
+@accel_key:
+@accel_mods:
+@accel_flags:
+
<!-- ##### SIGNAL GtkWidget::debug-msg ##### -->
<para>
@@ -1237,6 +1272,16 @@ the #GtkAdjustment which sets the range of the scale.
@widget: the object which received the signal.
+<!-- ##### SIGNAL GtkWidget::remove-accelerator ##### -->
+<para>
+
+</para>
+
+@widget: the object which received the signal.
+@accel_group:
+@accel_key:
+@accel_mods:
+
<!-- ##### ARG GtkWidget:height ##### -->
<para>
@@ -1273,6 +1318,37 @@ If the window shrinks automatically when widgets within it shrink.
</para>
+<!-- ##### FUNCTION gtk_accel_group_activate ##### -->
+<para>
+
+</para>
+
+@accel_group:
+@accel_key:
+@accel_mods:
+@Returns:
+
+<!-- ##### FUNCTION gtk_accel_group_add ##### -->
+<para>
+
+</para>
+
+@accel_group:
+@path:
+@accel_key:
+@accel_mods:
+@accel_flags:
+@object:
+@accel_signal:
+
+<!-- ##### FUNCTION gtk_accel_group_attach ##### -->
+<para>
+
+</para>
+
+@accel_group:
+@object:
+
<!-- ##### FUNCTION gtk_accel_group_create_add ##### -->
<para>
@@ -1293,6 +1369,14 @@ If the window shrinks automatically when widgets within it shrink.
@handler_offset:
@Returns:
+<!-- ##### FUNCTION gtk_accel_group_detach ##### -->
+<para>
+
+</para>
+
+@accel_group:
+@object:
+
<!-- ##### FUNCTION gtk_accel_group_entries_from_object ##### -->
<para>
@@ -1301,6 +1385,13 @@ If the window shrinks automatically when widgets within it shrink.
@object:
@Returns:
+<!-- ##### FUNCTION gtk_accel_group_get_default ##### -->
+<para>
+
+</para>
+
+@Returns:
+
<!-- ##### FUNCTION gtk_accel_group_get_entry ##### -->
<para>
@@ -1342,6 +1433,24 @@ If the window shrinks automatically when widgets within it shrink.
@accel_key:
@accel_mods:
+<!-- ##### MACRO gtk_accel_group_ref ##### -->
+<para>
+
+</para>
+
+@Returns:
+@accel_group:
+
+<!-- ##### FUNCTION gtk_accel_group_remove ##### -->
+<para>
+
+</para>
+
+@accel_group:
+@accel_key:
+@accel_mods:
+@object:
+
<!-- ##### FUNCTION gtk_accel_group_unlock_entry ##### -->
<para>
@@ -1351,6 +1460,13 @@ If the window shrinks automatically when widgets within it shrink.
@accel_key:
@accel_mods:
+<!-- ##### MACRO gtk_accel_group_unref ##### -->
+<para>
+
+</para>
+
+@accel_group:
+
<!-- ##### FUNCTION gtk_accel_groups_from_object ##### -->
<para>
@@ -1359,6 +1475,22 @@ If the window shrinks automatically when widgets within it shrink.
@object:
@Returns:
+<!-- ##### FUNCTION gtk_accel_label_get_accel_object ##### -->
+<para>
+
+</para>
+
+@accel_label:
+@Returns:
+
+<!-- ##### FUNCTION gtk_accel_label_set_accel_object ##### -->
+<para>
+
+</para>
+
+@accel_label:
+@accel_object:
+
<!-- ##### FUNCTION gtk_arg_copy ##### -->
<para>
It will either copy data into an existing argument or allocate a new argument
@@ -1905,6 +2037,54 @@ Get the type of GtkIdentifier.
@Returns:
+<!-- ##### FUNCTION gtk_item_factory_dump_items ##### -->
+<para>
+
+</para>
+
+@path_pspec:
+@modified_only:
+@print_func:
+@func_data:
+
+<!-- ##### FUNCTION gtk_item_factory_dump_rc ##### -->
+<para>
+
+</para>
+
+@file_name:
+@path_pspec:
+@modified_only:
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc ##### -->
+<para>
+
+</para>
+
+@file_name:
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc_scanner ##### -->
+<para>
+
+</para>
+
+@scanner:
+
+<!-- ##### FUNCTION gtk_item_factory_parse_rc_string ##### -->
+<para>
+
+</para>
+
+@rc_string:
+
+<!-- ##### FUNCTION gtk_item_factory_print_func ##### -->
+<para>
+
+</para>
+
+@FILE_pointer:
+@string:
+
<!-- ##### FUNCTION gtk_label_set_markup_with_accel ##### -->
<para>
@@ -2715,6 +2895,31 @@ a gtk_object_unref().
@width:
@size:
+<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_dest ##### -->
+<para>
+
+</para>
+
+@tree_view:
+@targets:
+@n_targets:
+@actions:
+@location_droppable_func:
+@user_data:
+
+<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_source ##### -->
+<para>
+
+</para>
+
+@tree_view:
+@start_button_mask:
+@targets:
+@n_targets:
+@actions:
+@row_draggable_func:
+@user_data:
+
<!-- ##### FUNCTION gtk_type_check_class_cast ##### -->
<para>
Given a GtkTypeClass pointer @klass, and a GtkType @cast_type, make
@@ -2829,6 +3034,25 @@ Set the varargs type for a fundamental type @foreign_type.
fundamental type.
@varargs_type: Must be a GtkType which is either structured or flag, or NONE.
+<!-- ##### FUNCTION gtk_widget_accelerator_signal ##### -->
+<para>
+
+</para>
+
+@widget:
+@accel_group:
+@accel_key:
+@accel_mods:
+@Returns:
+
+<!-- ##### FUNCTION gtk_widget_accelerators_locked ##### -->
+<para>
+
+</para>
+
+@widget:
+@Returns:
+
<!-- ##### FUNCTION gtk_widget_activate_mnemonic ##### -->
<para>
@@ -2847,6 +3071,13 @@ fundamental type.
@width:
@height:
+<!-- ##### FUNCTION gtk_widget_lock_accelerators ##### -->
+<para>
+
+</para>
+
+@widget:
+
<!-- ##### FUNCTION gtk_widget_pop_style ##### -->
<para>
@@ -2869,6 +3100,15 @@ fundamental type.
@style:
+<!-- ##### FUNCTION gtk_widget_remove_accelerators ##### -->
+<para>
+
+</para>
+
+@widget:
+@accel_signal:
+@visible_only:
+
<!-- ##### FUNCTION gtk_widget_set_default_style ##### -->
<para>
@@ -2876,6 +3116,13 @@ fundamental type.
@style:
+<!-- ##### FUNCTION gtk_widget_unlock_accelerators ##### -->
+<para>
+
+</para>
+
+@widget:
+
<!-- ##### FUNCTION gtk_window_activate_mnemonic ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkaccelgroup.sgml b/docs/reference/gtk/tmpl/gtkaccelgroup.sgml
index a0fc59a529..b069f7e738 100644
--- a/docs/reference/gtk/tmpl/gtkaccelgroup.sgml
+++ b/docs/reference/gtk/tmpl/gtkaccelgroup.sgml
@@ -1,9 +1,9 @@
<!-- ##### SECTION Title ##### -->
-Keyboard Accelerators
+Keyboard Accelerator Groups
<!-- ##### SECTION Short_Description ##### -->
-global keyboard accelerators (for an entire #GtkWindow)
+Groups of global keyboard accelerators for an entire #GtkWindow
<!-- ##### SECTION Long_Description ##### -->
<para>
@@ -11,14 +11,15 @@ A #GtkAccelGroup represents a group of keyboard accelerators,
typically attached to a toplevel #GtkWindow (with
gtk_window_add_accel_group()). Usually you won't need to create a
#GtkAccelGroup directly; instead, when using #GtkItemFactory, GTK+
-automatically sets up the accelerators for your menus.
+automatically sets up the accelerators for your menus in the item
+factory's #GtkAccelGroup.
</para>
<para>
Note that <firstterm>accelerators</firstterm> are different from
<firstterm>mnemonics</firstterm>. Accelerators are shortcuts for
activating a menu item; they appear alongside the menu item they're a
-shortcut for, for example "Ctrl+Q" might appear alongside the "Quit"
+shortcut for. For example "Ctrl+Q" might appear alongside the "Quit"
menu item. Mnemonics are shortcuts for GUI elements such as text
entries or buttons; they appear as underlined characters. See
gtk_label_new_with_mnemonic(). Menu items can have both accelerators
@@ -27,16 +28,17 @@ and mnemonics, of course.
<!-- ##### SECTION See_Also ##### -->
<para>
-gtk_label_new_with_mnemonic(), gtk_window_add_accel_group()
+gtk_window_add_accel_group(), gtk_accel_map_change_entry(),
+gtk_item_factory_new(), gtk_label_new_with_mnemonic()
</para>
<!-- ##### STRUCT GtkAccelGroup ##### -->
<para>
-On opaque data type representing a group of accelerators.
+An object representing and maintaining a group of accelerators.
</para>
-<!-- ##### FUNCTION gtk_accel_group_new ##### -->
+<!-- ##### FUNCTION gtk_accel_group_get_type ##### -->
<para>
</para>
@@ -44,32 +46,15 @@ On opaque data type representing a group of accelerators.
@Returns:
-<!-- ##### FUNCTION gtk_accel_group_get_default ##### -->
-<para>
-
-</para>
-
-@Returns:
-
-
-<!-- ##### FUNCTION gtk_accel_group_ref ##### -->
+<!-- ##### FUNCTION gtk_accel_group_new ##### -->
<para>
</para>
-@accel_group:
@Returns:
-<!-- ##### FUNCTION gtk_accel_group_unref ##### -->
-<para>
-
-</para>
-
-@accel_group:
-
-
-<!-- ##### FUNCTION gtk_accel_group_activate ##### -->
+<!-- ##### FUNCTION gtk_accel_group_connect ##### -->
<para>
</para>
@@ -77,39 +62,25 @@ On opaque data type representing a group of accelerators.
@accel_group:
@accel_key:
@accel_mods:
-@Returns:
+@accel_flags:
+@closure:
+@accel_path_quark:
+<!-- # Unused Parameters # -->
+@path_quark:
-<!-- ##### FUNCTION gtk_accel_groups_activate ##### -->
+<!-- ##### FUNCTION gtk_accel_group_disconnect ##### -->
<para>
</para>
-@object:
+@accel_group:
@accel_key:
@accel_mods:
@Returns:
-<!-- ##### FUNCTION gtk_accel_group_attach ##### -->
-<para>
-
-</para>
-
-@accel_group:
-@object:
-
-
-<!-- ##### FUNCTION gtk_accel_group_detach ##### -->
-<para>
-
-</para>
-
-@accel_group:
-@object:
-
-
-<!-- ##### FUNCTION gtk_accel_group_add ##### -->
+<!-- ##### FUNCTION gtk_accel_group_query ##### -->
<para>
</para>
@@ -117,19 +88,20 @@ On opaque data type representing a group of accelerators.
@accel_group:
@accel_key:
@accel_mods:
-@accel_flags:
-@object:
-@accel_signal:
+@n_entries:
+@Returns:
-<!-- ##### FUNCTION gtk_accel_group_remove ##### -->
+<!-- ##### FUNCTION gtk_accel_groups_activate ##### -->
<para>
</para>
-@accel_group:
+@acceleratable:
@accel_key:
@accel_mods:
+@Returns:
+<!-- # Unused Parameters # -->
@object:
diff --git a/docs/reference/gtk/tmpl/gtkaccellabel.sgml b/docs/reference/gtk/tmpl/gtkaccellabel.sgml
index a434252bbd..4587cf7515 100644
--- a/docs/reference/gtk/tmpl/gtkaccellabel.sgml
+++ b/docs/reference/gtk/tmpl/gtkaccellabel.sgml
@@ -94,7 +94,7 @@ Creates a new #GtkAccelLabel.
@Returns: a new #GtkAccelLabel.
-<!-- ##### FUNCTION gtk_accel_label_get_accel_object ##### -->
+<!-- ##### FUNCTION gtk_accel_label_get_accel_widget ##### -->
<para>
</para>
@@ -103,24 +103,7 @@ Creates a new #GtkAccelLabel.
@Returns:
-<!-- ##### FUNCTION gtk_accel_label_set_accel_object ##### -->
-<para>
-
-</para>
-
-@accel_label:
-@accel_object:
-
-
-<!-- ##### MACRO gtk_accel_label_get_accel_widget ##### -->
-<para>
-
-</para>
-
-@accel_label:
-
-
-<!-- ##### MACRO gtk_accel_label_set_accel_widget ##### -->
+<!-- ##### FUNCTION gtk_accel_label_set_accel_widget ##### -->
<para>
Sets the widget whose accelerators are to be shown.
</para>
@@ -151,8 +134,13 @@ accelerators are added or removed from the associated widget.
@Returns: always returns %FALSE.
-<!-- ##### ARG GtkAccelLabel:accel-object ##### -->
+<!-- ##### ARG GtkAccelLabel:accel-closure ##### -->
<para>
</para>
+<!-- ##### ARG GtkAccelLabel:accel-widget ##### -->
+<para>
+The widget whose accelerators are to be shown by the #GtkAccelLabel.
+</para>
+
diff --git a/docs/reference/gtk/tmpl/gtkcolorsel.sgml b/docs/reference/gtk/tmpl/gtkcolorsel.sgml
index 73907ce289..5bb58e1229 100644
--- a/docs/reference/gtk/tmpl/gtkcolorsel.sgml
+++ b/docs/reference/gtk/tmpl/gtkcolorsel.sgml
@@ -225,7 +225,7 @@ time.
</para>
-@colorsel:
+@colorsel:
@color:
@@ -234,8 +234,8 @@ time.
</para>
-@colorsel:
-@color:
+@colorsel:
+@color:
<!-- ##### SIGNAL GtkColorSelection::color-changed ##### -->
diff --git a/docs/reference/gtk/tmpl/gtkcombo.sgml b/docs/reference/gtk/tmpl/gtkcombo.sgml
index 8034f9cb78..4f6ed7b6fe 100644
--- a/docs/reference/gtk/tmpl/gtkcombo.sgml
+++ b/docs/reference/gtk/tmpl/gtkcombo.sgml
@@ -178,7 +178,7 @@ worried about differences in case.
</para>
@combo: a #GtkCombo.
-@val: %TRUE if the text in the list items is case sensitive.
+@val: %TRUE if the text in the list items is case sensitive.
<!-- ##### FUNCTION gtk_combo_set_item_string ##### -->
diff --git a/docs/reference/gtk/tmpl/gtkdialog.sgml b/docs/reference/gtk/tmpl/gtkdialog.sgml
index f677af775d..7eb449fe1a 100644
--- a/docs/reference/gtk/tmpl/gtkdialog.sgml
+++ b/docs/reference/gtk/tmpl/gtkdialog.sgml
@@ -169,7 +169,7 @@ Creates a new dialog box. Widgets should not be packed into this #GtkWindow
directly, but into the vbox and action_area, as described above.
</para>
-@Returns: a new #GtkDialog.
+@Returns: a new #GtkDialog.
<!-- ##### FUNCTION gtk_dialog_new_with_buttons ##### -->
diff --git a/docs/reference/gtk/tmpl/gtkenums.sgml b/docs/reference/gtk/tmpl/gtkenums.sgml
index 6c19bccb73..304ae8d02e 100644
--- a/docs/reference/gtk/tmpl/gtkenums.sgml
+++ b/docs/reference/gtk/tmpl/gtkenums.sgml
@@ -20,7 +20,6 @@ Public enumerated types used throughout GTK+.
</para>
@GTK_ACCEL_VISIBLE:
-@GTK_ACCEL_SIGNAL_VISIBLE:
@GTK_ACCEL_LOCKED:
@GTK_ACCEL_MASK:
diff --git a/docs/reference/gtk/tmpl/gtkitemfactory.sgml b/docs/reference/gtk/tmpl/gtkitemfactory.sgml
index abda892595..57c1fd8f71 100644
--- a/docs/reference/gtk/tmpl/gtkitemfactory.sgml
+++ b/docs/reference/gtk/tmpl/gtkitemfactory.sgml
@@ -84,11 +84,6 @@ GtkItemFactory
</para>
@path:
-@accelerator_key:
-@accelerator_mods:
-@modified:
-@in_propagation:
-@dummy:
@widgets:
<!-- ##### FUNCTION gtk_item_factory_new ##### -->
@@ -113,30 +108,6 @@ GtkItemFactory
@accel_group:
-<!-- ##### FUNCTION gtk_item_factory_parse_rc ##### -->
-<para>
-
-</para>
-
-@file_name:
-
-
-<!-- ##### FUNCTION gtk_item_factory_parse_rc_string ##### -->
-<para>
-
-</para>
-
-@rc_string:
-
-
-<!-- ##### FUNCTION gtk_item_factory_parse_rc_scanner ##### -->
-<para>
-
-</para>
-
-@scanner:
-
-
<!-- ##### FUNCTION gtk_item_factory_add_foreign ##### -->
<para>
@@ -207,36 +178,6 @@ GtkItemFactory
@Returns:
-<!-- ##### FUNCTION gtk_item_factory_dump_items ##### -->
-<para>
-
-</para>
-
-@path_pspec:
-@modified_only:
-@print_func:
-@func_data:
-
-
-<!-- ##### FUNCTION gtk_item_factory_dump_rc ##### -->
-<para>
-
-</para>
-
-@file_name:
-@path_pspec:
-@modified_only:
-
-
-<!-- ##### FUNCTION gtk_item_factory_print_func ##### -->
-<para>
-
-</para>
-
-@FILE_pointer:
-@string:
-
-
<!-- ##### FUNCTION gtk_item_factory_create_item ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkmenu.sgml b/docs/reference/gtk/tmpl/gtkmenu.sgml
index 8bb20423d8..eb37062f02 100644
--- a/docs/reference/gtk/tmpl/gtkmenu.sgml
+++ b/docs/reference/gtk/tmpl/gtkmenu.sgml
@@ -96,9 +96,9 @@ Creates a new #GtkMenu.
Adds a new #GtkMenuItem to the end of the menu's item list.
</para>
-<!-- # Unused Parameters # -->
@menu: a #GtkMenu.
@child: The #GtkMenuItem to add.
+<!-- # Unused Parameters # -->
@m:
@c:
@@ -108,9 +108,9 @@ Adds a new #GtkMenuItem to the end of the menu's item list.
Adds a new #GtkMenuItem to the beginning of the menu's item list.
</para>
-<!-- # Unused Parameters # -->
@menu: a #GtkMenu.
@child: The #GtkMenuItem to add.
+<!-- # Unused Parameters # -->
@menu_child:
@m:
@c:
@@ -122,10 +122,10 @@ Adds a new #GtkMenuItem to the menu's item list at the position
indicated by @position.
</para>
-<!-- # Unused Parameters # -->
@menu: a #GtkMenu.
@child: The #GtkMenuItem to add.
@pos:
+<!-- # Unused Parameters # -->
@position: The position in the item list where @child is added.
Positions are numbered from 0 to n-1.
@@ -162,6 +162,9 @@ at the current pointer position.
<!-- ##### FUNCTION gtk_menu_set_accel_group ##### -->
<para>
Set the #GtkAccelGroup which holds global accelerators for the menu.
+This accelerator group needs to also be added to all windows that
+this menu is being used in with gtk_window_add_accel_group(), in order
+for those windows to support all the accelerators contained in this group.
</para>
@menu: a #GtkMenu.
@@ -178,6 +181,15 @@ See gtk_menu_set_accel_group().
@Returns: the #GtkAccelGroup associated with the menu.
+<!-- ##### FUNCTION gtk_menu_set_accel_path ##### -->
+<para>
+
+</para>
+
+@menu:
+@accel_path:
+
+
<!-- ##### FUNCTION gtk_menu_set_title ##### -->
<para>
Sets the title string for the menu. The title is displayed when the menu
diff --git a/docs/reference/gtk/tmpl/gtkmenuitem.sgml b/docs/reference/gtk/tmpl/gtkmenuitem.sgml
index 76b4e86398..d65e13a75e 100644
--- a/docs/reference/gtk/tmpl/gtkmenuitem.sgml
+++ b/docs/reference/gtk/tmpl/gtkmenuitem.sgml
@@ -83,6 +83,15 @@ Sets the widget submenu, or changes it.
@submenu: the submenu
+<!-- ##### FUNCTION gtk_menu_item_set_accel_path ##### -->
+<para>
+
+</para>
+
+@menu_item:
+@accel_path:
+
+
<!-- ##### FUNCTION gtk_menu_item_remove_submenu ##### -->
<para>
Removes the widget's submenu.
diff --git a/docs/reference/gtk/tmpl/gtkpaned.sgml b/docs/reference/gtk/tmpl/gtkpaned.sgml
index f3a7e01e09..95369862de 100644
--- a/docs/reference/gtk/tmpl/gtkpaned.sgml
+++ b/docs/reference/gtk/tmpl/gtkpaned.sgml
@@ -112,6 +112,9 @@ Old name for gtk_paned_set_handle_size()
Old name for gtk_paned_set_gutter_size()
</para>
+@p:
+@s:
+
<!-- ##### FUNCTION gtk_paned_pack1 ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtktoolbar.sgml b/docs/reference/gtk/tmpl/gtktoolbar.sgml
index 9ee5eb8542..74562454d8 100644
--- a/docs/reference/gtk/tmpl/gtktoolbar.sgml
+++ b/docs/reference/gtk/tmpl/gtktoolbar.sgml
@@ -47,8 +47,8 @@ Widgets can be visibly grouped by adding gaps between widgets using gtk_toolbar_
to a #GtkToolbar.
</para>
-@GTK_TOOLBAR_CHILD_SPACE: a space in the style of the toolbar's #GtkToolbarSpaceStyle.
-@GTK_TOOLBAR_CHILD_BUTTON: a #GtkButton.
+@GTK_TOOLBAR_CHILD_SPACE: a space in the style of the toolbar's #GtkToolbarSpaceStyle.
+@GTK_TOOLBAR_CHILD_BUTTON: a #GtkButton.
@GTK_TOOLBAR_CHILD_TOGGLEBUTTON: a #GtkToggleButton.
@GTK_TOOLBAR_CHILD_RADIOBUTTON: a #GtkRadioButton.
@GTK_TOOLBAR_CHILD_WIDGET: a standard #GtkWidget.
diff --git a/docs/reference/gtk/tmpl/gtktreednd.sgml b/docs/reference/gtk/tmpl/gtktreednd.sgml
index 842769a899..9414655b6b 100644
--- a/docs/reference/gtk/tmpl/gtktreednd.sgml
+++ b/docs/reference/gtk/tmpl/gtktreednd.sgml
@@ -43,6 +43,7 @@ GtkTreeView drag-and-drop
</para>
@g_iface:
+@row_draggable:
@drag_data_get:
@drag_data_delete:
diff --git a/docs/reference/gtk/tmpl/gtktreeview.sgml b/docs/reference/gtk/tmpl/gtktreeview.sgml
index 3234cc1c0b..b8480449e8 100644
--- a/docs/reference/gtk/tmpl/gtktreeview.sgml
+++ b/docs/reference/gtk/tmpl/gtktreeview.sgml
@@ -49,18 +49,6 @@ GtkTreeView
@Returns:
-<!-- ##### USER_FUNCTION GtkTreeViewDraggableFunc ##### -->
-<para>
-
-</para>
-
-@tree_view:
-@context:
-@path:
-@user_data:
-@Returns:
-
-
<!-- ##### USER_FUNCTION GtkTreeViewMappingFunc ##### -->
<para>
@@ -71,19 +59,6 @@ GtkTreeView
@user_data:
-<!-- ##### USER_FUNCTION GtkTreeViewDroppableFunc ##### -->
-<para>
-
-</para>
-
-@tree_view:
-@context:
-@path:
-@pos:
-@user_data:
-@Returns:
-
-
<!-- ##### USER_FUNCTION GtkTreeViewSearchEqualFunc ##### -->
<para>
@@ -559,33 +534,6 @@ GtkTreeView
@wy:
-<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_source ##### -->
-<para>
-
-</para>
-
-@tree_view:
-@start_button_mask:
-@targets:
-@n_targets:
-@actions:
-@row_draggable_func:
-@user_data:
-
-
-<!-- ##### FUNCTION gtk_tree_view_set_rows_drag_dest ##### -->
-<para>
-
-</para>
-
-@tree_view:
-@targets:
-@n_targets:
-@actions:
-@location_droppable_func:
-@user_data:
-
-
<!-- ##### FUNCTION gtk_tree_view_unset_rows_drag_source ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkwidget.sgml b/docs/reference/gtk/tmpl/gtkwidget.sgml
index 4781aee5fd..76769b73b5 100644
--- a/docs/reference/gtk/tmpl/gtkwidget.sgml
+++ b/docs/reference/gtk/tmpl/gtkwidget.sgml
@@ -527,27 +527,6 @@ GtkWidget
@accel_group:
@accel_key:
@accel_mods:
-
-
-<!-- ##### FUNCTION gtk_widget_remove_accelerators ##### -->
-<para>
-
-</para>
-
-@widget:
-@accel_signal:
-@visible_only:
-
-
-<!-- ##### FUNCTION gtk_widget_accelerator_signal ##### -->
-<para>
-
-</para>
-
-@widget:
-@accel_group:
-@accel_key:
-@accel_mods:
@Returns:
@@ -1000,14 +979,6 @@ GtkWidget
@Returns:
-<!-- ##### FUNCTION gtk_widget_lock_accelerators ##### -->
-<para>
-
-</para>
-
-@widget:
-
-
<!-- ##### FUNCTION gtk_widget_modify_style ##### -->
<para>
@@ -1207,23 +1178,6 @@ GtkWidget
@Returns:
-<!-- ##### FUNCTION gtk_widget_unlock_accelerators ##### -->
-<para>
-
-</para>
-
-@widget:
-
-
-<!-- ##### FUNCTION gtk_widget_accelerators_locked ##### -->
-<para>
-
-</para>
-
-@widget:
-@Returns:
-
-
<!-- ##### FUNCTION gtk_widget_mnemonic_activate ##### -->
<para>
@@ -1456,17 +1410,12 @@ GtkWidget
@requisition:
-<!-- ##### SIGNAL GtkWidget::add-accelerator ##### -->
+<!-- ##### SIGNAL GtkWidget::accel-closures-changed ##### -->
<para>
</para>
@widget: the object which received the signal.
-@accel_signal_id:
-@accel_group:
-@accel_key:
-@accel_mods:
-@accel_flags:
<!-- ##### SIGNAL GtkWidget::button-press-event ##### -->
<para>
@@ -1834,16 +1783,6 @@ a widget changes from un-anchored to anchored or vice-versa.
@widget: the object which received the signal.
-<!-- ##### SIGNAL GtkWidget::remove-accelerator ##### -->
-<para>
-
-</para>
-
-@widget: the object which received the signal.
-@accel_group:
-@accel_key:
-@accel_mods:
-
<!-- ##### SIGNAL GtkWidget::scroll-event ##### -->
<para>
diff --git a/docs/reference/gtk/tmpl/gtkwindow.sgml b/docs/reference/gtk/tmpl/gtkwindow.sgml
index 66ea516399..b8111b4362 100644
--- a/docs/reference/gtk/tmpl/gtkwindow.sgml
+++ b/docs/reference/gtk/tmpl/gtkwindow.sgml
@@ -694,6 +694,13 @@ it's larger
@height:
+<!-- ##### SIGNAL GtkWindow::accels-changed ##### -->
+<para>
+
+</para>
+
+@window: the object which received the signal.
+
<!-- ##### SIGNAL GtkWindow::activate-default ##### -->
<para>
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index bef5917e0a..bbe5fa6fe2 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -86,6 +86,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtk.h \
gtkaccelgroup.h \
gtkaccellabel.h \
+ gtkaccelmap.h \
gtkaccessible.h \
gtkadjustment.h \
gtkalignment.h \
@@ -244,6 +245,7 @@ gtk_private_h_sources = @STRIP_BEGIN@ \
# GTK+ C sources to build the library from
gtk_c_sources = @STRIP_BEGIN@ \
gtkaccelgroup.c \
+ gtkaccelmap.c \
gtkaccellabel.c \
gtkaccessible.c \
gtkadjustment.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index d7d802973d..9a9016e64f 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -31,6 +31,7 @@
#include <gdk/gdk.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkaccellabel.h>
+#include <gtk/gtkaccelmap.h>
#include <gtk/gtkaccessible.h>
#include <gtk/gtkadjustment.h>
#include <gtk/gtkalignment.h>
diff --git a/gtk/gtkaccelgroup.c b/gtk/gtkaccelgroup.c
index 0464ecd7ce..a8c36b7643 100644
--- a/gtk/gtkaccelgroup.c
+++ b/gtk/gtkaccelgroup.c
@@ -1,8 +1,5 @@
/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GtkAccelGroup: Accelerator manager for GtkObjects.
- * Copyright (C) 1998 Tim Janik
+ * Copyright (C) 1998, 2001 Tim Janik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,79 +23,37 @@
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-
-#include <ctype.h>
-#include <string.h>
#include "gtkaccelgroup.h"
+#include "gtkaccelmap.h"
#include "gdk/gdkkeysyms.h"
#include "gtksignal.h"
-#include "gtkwidget.h"
-
-
-/* --- signals --- */
-typedef void (*GtkSignalAddAccelerator) (GObject *object,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags,
- gpointer func_data);
-typedef void (*GtkSignalRemoveAccelerator) (GObject *object,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- gpointer func_data);
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+/* --- prototypes --- */
+static void gtk_accel_group_class_init (GtkAccelGroupClass *class);
+static void gtk_accel_group_init (GtkAccelGroup *accel_group);
+static void gtk_accel_group_finalize (GObject *object);
+
/* --- variables --- */
-static GtkAccelGroup *default_accel_group = NULL;
+static GObjectClass *parent_class = NULL;
+static guint signal_accel_activate = 0;
+static guint signal_accel_changed = 0;
+static guint quark_acceleratable_groups = 0;
static guint default_accel_mod_mask = (GDK_SHIFT_MASK |
GDK_CONTROL_MASK |
GDK_MOD1_MASK);
-static const gchar *accel_groups_key = "gtk-accel-groups";
-static guint accel_groups_key_id = 0;
-static const gchar *accel_entries_key = "gtk-accel-entries";
-static guint accel_entries_key_id = 0;
-static GHashTable *accel_entry_hash_table = NULL;
-static GMemChunk *accel_entries_mem_chunk = NULL;
-
-static GObjectClass *parent_class = NULL;
/* --- functions --- */
-static gboolean
-gtk_accel_entries_equal (gconstpointer a,
- gconstpointer b)
-{
- const GtkAccelEntry *e1;
- const GtkAccelEntry *e2;
-
- e1 = a;
- e2 = b;
-
- return ((e1->accel_group == e2->accel_group) &&
- (e1->accelerator_key == e2->accelerator_key) &&
- (e1->accelerator_mods == e2->accelerator_mods));
-}
-
-static guint
-gtk_accel_entries_hash (gconstpointer a)
-{
- const GtkAccelEntry *e;
- guint h;
-
- e = a;
-
- h = (gulong) e->accel_group;
- h ^= e->accelerator_key << 16;
- h ^= e->accelerator_key >> 16;
- h ^= e->accelerator_mods;
-
- return h;
-}
-
-static void gtk_accel_group_class_init (GObjectClass *class);
-static void gtk_accel_group_init (GtkAccelGroup *accel_group);
-
+/**
+ * gtk_accel_map_change_entry
+ * @returns: the type ID for accelerator groups
+ */
GType
gtk_accel_group_get_type (void)
{
@@ -106,15 +61,14 @@ gtk_accel_group_get_type (void)
if (!object_type)
{
- static const GTypeInfo object_info =
- {
+ static const GTypeInfo object_info = {
sizeof (GtkAccelGroupClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gtk_accel_group_class_init,
NULL, /* clas_finalize */
NULL, /* class_data */
- sizeof(GtkAccelGroup),
+ sizeof (GtkAccelGroup),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_accel_group_init,
};
@@ -127,120 +81,90 @@ gtk_accel_group_get_type (void)
return object_type;
}
-static void
-gtk_accel_group_finalize (GObject *object)
+static gboolean
+accel_activate_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer data)
{
- GtkAccelGroup *accel_group = GTK_ACCEL_GROUP(object);
+ gboolean continue_emission;
+ gboolean handler_val;
- if (accel_group == default_accel_group)
- g_warning (G_STRLOC "default accel group should not be finalized");
+ /* handler returns whether the accelerator was handled */
+ handler_val = g_value_get_boolean (handler_return);
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
+ /* record that as result for this emission */
+ g_value_set_boolean (return_accu, handler_val);
-static void
-gtk_accel_group_class_init (GObjectClass *class)
-{
- parent_class = g_type_class_ref (G_TYPE_OBJECT);
+ /* don't continue if accelerator was handled */
+ continue_emission = !handler_val;
- class->finalize = gtk_accel_group_finalize;
+ return continue_emission;
}
static void
-gtk_accel_group_init (GtkAccelGroup *accel_group)
+gtk_accel_group_class_init (GtkAccelGroupClass *class)
{
- if (!accel_groups_key_id)
- {
- accel_groups_key_id = g_quark_from_static_string (accel_groups_key);
- accel_entries_key_id = g_quark_from_static_string (accel_entries_key);
-
- accel_entry_hash_table = g_hash_table_new (gtk_accel_entries_hash,
- gtk_accel_entries_equal);
-
- accel_entries_mem_chunk = g_mem_chunk_create (GtkAccelEntry, 64, G_ALLOC_AND_FREE);
- }
-
- accel_group->lock_count = 0;
- accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
- accel_group->attach_objects = NULL;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ quark_acceleratable_groups = g_quark_from_static_string ("gtk-acceleratable-accel-groups");
+
+ object_class->finalize = gtk_accel_group_finalize;
+
+ class->accel_changed = NULL;
+ signal_accel_activate = g_signal_new ("accel_activate",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_DETAILED,
+ 0,
+ accel_activate_accumulator, NULL,
+ gtk_marshal_BOOLEAN__OBJECT_UINT_UINT,
+ G_TYPE_BOOLEAN, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT);
+ signal_accel_changed = g_signal_new ("accel_changed",
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (GtkAccelGroupClass, accel_changed),
+ NULL, NULL,
+ gtk_marshal_VOID__UINT_UINT_BOXED,
+ G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_CLOSURE);
}
-/**
- * gtk_accel_group_new:
- *
- * Creates a new #GtkAccelGroup.
- *
- * Return value: a new #GtkAccelGroup
- **/
-GtkAccelGroup*
-gtk_accel_group_new (void)
+static void
+gtk_accel_group_finalize (GObject *object)
{
- GtkAccelGroup *accel_group;
+ GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
- accel_group = (GtkAccelGroup *)g_object_new(GTK_TYPE_ACCEL_GROUP, NULL);
+ g_free (accel_group->priv_accels);
- return accel_group;
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
-/**
- * gtk_accel_group_get_default:
- *
- * Gets the global default accelerator group; this is a fallback
- * used for all objects when gtk_accel_groups_activate() is called
- * on them. As such it's probably not appropriate for most uses.
- * (Accelerators are normally specific to a document window or the
- * like, rather than global to an application.)
- *
- * The returned value does not have its reference count incremented,
- * and should not be unreferenced.
- *
- * Return value: the default accelerator group
- **/
-GtkAccelGroup*
-gtk_accel_group_get_default (void)
+static void
+gtk_accel_group_init (GtkAccelGroup *accel_group)
{
- if (!default_accel_group)
- default_accel_group = gtk_accel_group_new ();
-
- return default_accel_group;
+ accel_group->lock_count = 0;
+ accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
+ accel_group->acceleratables = NULL;
+ accel_group->n_accels = 0;
+ accel_group->priv_accels = NULL;
}
/**
- * gtk_accel_group_ref:
- * @accel_group: a #GtkAccelGroup
+ * gtk_accel_group_new
+ * @returns: a new #GtkAccelGroup object
*
- * This is simply equivalent to g_object_ref (G_OBJECT (@accel_group)),
- * and exists for historical reasons only.
- *
- * Return value: @accel_group
- **/
+ * Creates a new #GtkAccelGroup.
+ */
GtkAccelGroup*
-gtk_accel_group_ref (GtkAccelGroup *accel_group)
-{
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), NULL);
-
- return (GtkAccelGroup *)g_object_ref(accel_group);
-}
-
-/**
- * gtk_accel_group_unref:
- * @accel_group: a #GtkAccelGroup
- *
- * This is simply equivalent to g_object_unref (G_OBJECT (@accel_group)),
- * and exists for historical reasons only.
- *
- **/
-void
-gtk_accel_group_unref (GtkAccelGroup *accel_group)
+gtk_accel_group_new (void)
{
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-
- g_object_unref(accel_group);
+ return g_object_new (GTK_TYPE_ACCEL_GROUP, NULL);
}
static void
-gtk_accel_group_object_destroy (GSList *free_list,
- GObject *where_the_object_was)
+accel_group_weak_ref_detach (GSList *free_list,
+ GObject *stale_object)
{
GSList *slist;
@@ -249,646 +173,488 @@ gtk_accel_group_object_destroy (GSList *free_list,
GtkAccelGroup *accel_group;
accel_group = slist->data;
- accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, where_the_object_was);
+ accel_group->acceleratables = g_slist_remove (accel_group->acceleratables, stale_object);
g_object_unref (accel_group);
}
g_slist_free (free_list);
}
-/**
- * gtk_accel_group_attach:
- * @accel_group: a #GtkAccelGroup
- * @object: object to attach accelerators to
- *
- * Associate @accel_group with @object, such that calling
- * gtk_accel_groups_activate() on @object will activate accelerators
- * in @accel_group.
- *
- * After calling this function, you still own a reference to both
- * @accel_group and @object; gtk_accel_group_attach() will not
- * "adopt" a reference to either one.
- *
- **/
void
-gtk_accel_group_attach (GtkAccelGroup *accel_group,
- GObject *object)
+_gtk_accel_group_attach (GtkAccelGroup *accel_group,
+ GObject *object)
{
GSList *slist;
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (g_slist_find (accel_group->attach_objects, object) == NULL);
+ g_return_if_fail (g_slist_find (accel_group->acceleratables, object) == NULL);
- accel_group->attach_objects = g_slist_prepend (accel_group->attach_objects, object);
g_object_ref (accel_group);
- slist = g_object_get_qdata (object, accel_groups_key_id);
+ accel_group->acceleratables = g_slist_prepend (accel_group->acceleratables, object);
+ slist = g_object_get_qdata (object, quark_acceleratable_groups);
if (slist)
- g_object_weak_unref(object,
- (GWeakNotify)gtk_accel_group_object_destroy,
- slist);
+ g_object_weak_unref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
slist = g_slist_prepend (slist, accel_group);
- g_object_set_qdata (object, accel_groups_key_id, slist);
- g_object_weak_ref(object,
- (GWeakNotify)gtk_accel_group_object_destroy,
- slist);
+ g_object_set_qdata (object, quark_acceleratable_groups, slist);
+ g_object_weak_ref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
}
-/**
- * gtk_accel_group_detach:
- * @accel_group: a #GtkAccelGroup
- * @object: a #GObject
- *
- * Reverses the effects of gtk_accel_group_attach().
- *
- **/
void
-gtk_accel_group_detach (GtkAccelGroup *accel_group,
- GObject *object)
+_gtk_accel_group_detach (GtkAccelGroup *accel_group,
+ GObject *object)
{
GSList *slist;
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (g_slist_find (accel_group->attach_objects, object) != NULL);
+ g_return_if_fail (g_slist_find (accel_group->acceleratables, object) != NULL);
- accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, object);
- g_object_unref (accel_group);
- slist = g_object_get_qdata (object, accel_groups_key_id);
- g_object_weak_unref(object,
- (GWeakNotify)gtk_accel_group_object_destroy,
- slist);
+ accel_group->acceleratables = g_slist_remove (accel_group->acceleratables, object);
+ slist = g_object_get_qdata (object, quark_acceleratable_groups);
+ g_object_weak_unref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
slist = g_slist_remove (slist, accel_group);
- g_object_set_qdata (object, accel_groups_key_id, slist);
+ g_object_set_qdata (object, quark_acceleratable_groups, slist);
if (slist)
- g_object_weak_ref(object,
- (GWeakNotify)gtk_accel_group_object_destroy,
- slist);
+ g_object_weak_ref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
+ g_object_unref (accel_group);
+}
+
+GSList*
+gtk_accel_groups_from_acceleratable (GObject *object)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+ return g_object_get_qdata (object, quark_acceleratable_groups);
+}
+
+GtkAccelKey*
+gtk_accel_group_find (GtkAccelGroup *accel_group,
+ gboolean (*find_func) (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data),
+ gpointer data)
+{
+ GtkAccelKey *key = NULL;
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+ g_return_val_if_fail (find_func != NULL, NULL);
+
+ g_object_ref (accel_group);
+ for (i = 0; i < accel_group->n_accels; i++)
+ if (find_func (&accel_group->priv_accels[i].key,
+ accel_group->priv_accels[i].closure,
+ data))
+ {
+ key = &accel_group->priv_accels[i].key;
+ break;
+ }
+ g_object_unref (accel_group);
+
+ return key;
}
/**
- * gtk_accel_group_lock:
+ * gtk_accel_group_lock
* @accel_group: a #GtkAccelGroup
*
- * Prevents the addition of new accelerators to @accel_group.
- * Primarily used to avoid the "dynamic accelerator editing" feature
- * of #GtkMenu.
+ * Locking an acelerator group prevents the accelerators contained
+ * within it to be changed during runtime. Refer to
+ * gtk_accel_map_change_entry() about runtime accelerator changes.
*
* If called more than once, @accel_group remains locked until
* gtk_accel_group_unlock() has been called an equivalent number
* of times.
- *
- **/
+ */
void
-gtk_accel_group_lock (GtkAccelGroup *accel_group)
+gtk_accel_group_lock (GtkAccelGroup *accel_group)
{
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
accel_group->lock_count += 1;
}
/**
- * gtk_accel_group_unlock:
+ * gtk_accel_group_unlock
* @accel_group: a #GtkAccelGroup
*
- * Allows the addition of new accelerators to @accel_group.
- * Primarily used to enable the "dynamic accelerator editing" feature
- * of #GtkMenu.
- *
- **/
+ * This function undoes the last call to gtk_accel_group_lock()
+ * on this @accel_group.
+ */
void
-gtk_accel_group_unlock (GtkAccelGroup *accel_group)
+gtk_accel_group_unlock (GtkAccelGroup *accel_group)
{
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-
- if (accel_group->lock_count)
- accel_group->lock_count -= 1;
-}
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (accel_group->lock_count > 0);
-static GtkAccelEntry*
-gtk_accel_group_lookup (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
-{
- GtkAccelEntry key_entry = { 0 };
-
- key_entry.accel_group = accel_group;
- key_entry.accelerator_key = gdk_keyval_to_lower (accel_key);
- key_entry.accelerator_mods = accel_mods & accel_group->modifier_mask;
-
- return g_hash_table_lookup (accel_entry_hash_table, &key_entry);
+ accel_group->lock_count -= 1;
}
-/**
- * gtk_accel_group_activate:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: keyval from a key event
- * @accel_mods: modifier mask from a key event
- *
- * Checks whether a key event matches an accelerator in @accel_group;
- * if so, activates the accelerator, and returns %TRUE. Returns
- * %FALSE if no match.
- *
- * gtk_accel_groups_activate() should normally be used instead of
- * this function.
- *
- * Return value: %TRUE if an accelerator was activated
- **/
-gboolean
-gtk_accel_group_activate (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
+static void
+accel_tag_func (gpointer data,
+ GClosure *closure)
{
- GtkAccelEntry *entry;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), FALSE);
-
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry && entry->signal_id &&
- (!GTK_IS_WIDGET (entry->object) || GTK_WIDGET_IS_SENSITIVE (entry->object)))
- {
- g_signal_emit (entry->object, entry->signal_id, 0);
- return TRUE;
- }
- return FALSE;
+ /* GtkAccelGroup *accel_group = data; */
}
-/**
- * gtk_accel_groups_activate:
- * @object: a #GObject
- * @accel_key: accelerator keyval from a key event
- * @accel_mods: keyboard state mask from a key event
- *
- * Finds the first accelerator in any #GtkAccelGroup attached
- * to @object that matches @accel_key and @accel_mods, and
- * activates that accelerator. If no accelerators are found
- * in groups attached to @object, this function also tries
- * the default #GtkAccelGroup (see gtk_accel_group_get_default()).
- * If an accelerator is activated, returns %TRUE, otherwise
- * %FALSE.
- *
- * Return value: %TRUE if an accelerator was activated
- **/
-gboolean
-gtk_accel_groups_activate (GObject *object,
- guint accel_key,
- GdkModifierType accel_mods)
+static int
+bsearch_compare_accels (const void *d1,
+ const void *d2)
{
- g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-
- if (gtk_accelerator_valid (accel_key, accel_mods))
- {
- GSList *slist;
-
- for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
- if (gtk_accel_group_activate (slist->data, accel_key, accel_mods))
- return TRUE;
- return gtk_accel_group_activate (gtk_accel_group_get_default (), accel_key, accel_mods);
- }
-
- return FALSE;
+ const GtkAccelGroupEntry *entry1 = d1;
+ const GtkAccelGroupEntry *entry2 = d2;
+
+ if (entry1->key.accel_key == entry2->key.accel_key)
+ return entry1->key.accel_mods < entry2->key.accel_mods ? -1 : entry1->key.accel_mods > entry2->key.accel_mods;
+ else
+ return entry1->key.accel_key < entry2->key.accel_key ? -1 : 1;
}
-void
-gtk_accel_group_lock_entry (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
+static void
+quick_accel_add (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure,
+ GQuark path_quark)
{
- GtkAccelEntry *entry;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry)
- entry->accel_flags |= GTK_ACCEL_LOCKED;
+ guint pos, i = accel_group->n_accels++;
+ GtkAccelGroupEntry key;
+
+ key.key.accel_key = accel_key;
+ key.key.accel_mods = accel_mods;
+ for (pos = 0; pos < i; pos++)
+ if (bsearch_compare_accels (&key, accel_group->priv_accels + pos) < 0)
+ break;
+ accel_group->priv_accels = g_renew (GtkAccelGroupEntry, accel_group->priv_accels, accel_group->n_accels);
+ g_memmove (accel_group->priv_accels + pos + 1, accel_group->priv_accels + pos,
+ (i - pos) * sizeof (accel_group->priv_accels[0]));
+ accel_group->priv_accels[pos].key.accel_key = accel_key;
+ accel_group->priv_accels[pos].key.accel_mods = accel_mods;
+ accel_group->priv_accels[pos].key.accel_flags = accel_flags;
+ accel_group->priv_accels[pos].closure = g_closure_ref (closure);
+ accel_group->priv_accels[pos].accel_path_quark = path_quark;
+ g_closure_sink (closure);
+
+ /* tag closure for backwards lookup */
+ g_closure_add_invalidate_notifier (closure, accel_group, accel_tag_func);
}
-void
-gtk_accel_group_unlock_entry (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
+static GtkAccelGroupEntry*
+quick_accel_find (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ guint *count_p)
{
- GtkAccelEntry *entry;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
+ GtkAccelGroupEntry *entry;
+ GtkAccelGroupEntry key;
+
+ if (!accel_group->n_accels)
+ return NULL;
+
+ key.key.accel_key = accel_key;
+ key.key.accel_mods = accel_mods;
+ entry = bsearch (&key, accel_group->priv_accels, accel_group->n_accels,
+ sizeof (accel_group->priv_accels[0]), bsearch_compare_accels);
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry)
- entry->accel_flags &= ~GTK_ACCEL_LOCKED;
+ if (!entry)
+ return NULL;
+
+ /* step back to the first member */
+ for (; entry > accel_group->priv_accels; entry--)
+ if (entry[-1].key.accel_key != accel_key ||
+ entry[-1].key.accel_mods != accel_mods)
+ break;
+ /* count equal members */
+ for (*count_p = 0; entry + *count_p < accel_group->priv_accels + accel_group->n_accels; (*count_p)++)
+ if (entry[*count_p].key.accel_key != accel_key ||
+ entry[*count_p].key.accel_mods != accel_mods)
+ break;
+ return entry;
}
-GtkAccelEntry*
-gtk_accel_group_get_entry (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
+static GSList*
+quick_accel_remove (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods)
{
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP(accel_group), 0);
-
- return gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
+ guint i, n;
+ GtkAccelGroupEntry *entry = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+ guint pos = entry - accel_group->priv_accels;
+ GSList *clist = NULL;
+
+ if (!entry)
+ return NULL;
+ for (i = 0; i < n; i++)
+ {
+ g_closure_remove_invalidate_notifier (entry[i].closure, accel_group, accel_tag_func);
+ clist = g_slist_prepend (clist, entry[i].closure);
+ }
+
+ accel_group->n_accels -= n;
+ g_memmove (entry, entry + n,
+ (accel_group->n_accels - pos) * sizeof (accel_group->priv_accels[0]));
+
+ return clist;
}
/**
- * gtk_accel_group_add:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: accelerator keyval
- * @accel_mods: accelerator modifiers
- * @accel_flags: accelerator flags
- * @object: object that @accel_signal will be emitted on
- * @accel_signal: name of a #G_SIGNAL_ACTION signal to emit
- *
- * Adds an accelerator to @accel_group. When the accelerator is
- * activated, the @accel_signal signal will be emitted on @object.
- *
- * So for example, to click a button when Ctrl+a is pressed, you would
- * write: gtk_accel_group_add (accel_group, GDK_a, GDK_CONTROL_MASK,
- * 0, G_OBJECT (button), "clicked").
+ * gtk_accel_group_connect
+ * @accel_group: the ccelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @accel_flags: a flag mask to configure this accelerator
+ * @closure: closure to be executed upon accelerator activation
+ * @accel_path_quark: accelerator path quark from GtkAccelMapNotify
*
- * @accel_flags is not particularly useful, always pass 0 for
- * normal applications.
- *
- * @object must be an object that specifically supports accelerators,
- * such as #GtkWidget.
- **/
+ * Install an accelerator in this group. When @accel_group is being activated
+ * in response to a call to gtk_accel_groups_activate(), @closure will be
+ * invoked if the @accel_key and @accel_mods from gtk_accel_groups_activate()
+ * match those of this connection.
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ * If this connection is made in response to an accelerator path change (see
+ * gtk_accel_map_change_entry()) from a #GtkAccelMapNotify notifier,
+ * @accel_path_quark must be passed on from the notifier into this function,
+ * it should be 0 otherwise.
+ */
void
-gtk_accel_group_add (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags,
- GObject *object,
- const gchar *accel_signal)
+gtk_accel_group_connect (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure,
+ GQuark accel_path_quark)
{
- guint accel_signal_id = 0;
- guint add_accelerator_signal_id = 0;
- guint remove_accelerator_signal_id = 0;
- gchar *signal;
- GSignalQuery query;
- GSList *slist;
- GSList *groups;
- GSList *attach_objects;
- GtkAccelEntry *entry;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (accel_signal != NULL);
-
- /* check for required signals in the objects branch
- */
- signal = (gchar*) accel_signal;
- accel_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
- if (accel_signal_id)
- {
- signal = "add-accelerator";
- add_accelerator_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
- }
- if (add_accelerator_signal_id)
- {
- signal = "remove-accelerator";
- remove_accelerator_signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (object));
- }
- if (!accel_signal_id ||
- !add_accelerator_signal_id ||
- !remove_accelerator_signal_id)
- {
- g_warning ("gtk_accel_group_add(): could not find signal \"%s\""
- "in the `%s' class ancestry",
- signal,
- g_type_name (G_OBJECT_TYPE (object)));
- return;
- }
- g_signal_query (accel_signal_id, &query);
- if (!query.signal_id || query.n_params > 0)
- {
- g_warning ("gtk_accel_group_add(): signal \"%s\" in the `%s' class ancestry"
- "cannot be used as accelerator signal %s",
- accel_signal,
- g_type_name (G_OBJECT_TYPE (object)),
- query.n_params > 0 ? "(extraneous parameters are not supported)" : "");
- return;
- }
+ gchar *accel_name;
+ GQuark accel_quark;
+
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (accel_key > 0);
+
+ accel_name = gtk_accelerator_name (accel_key, accel_mods);
+ accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+
+ quick_accel_add (accel_group, accel_key, accel_mods, accel_flags, closure, accel_path_quark);
+
+ /* setup handler */
+ g_signal_connect_closure_by_id (accel_group, signal_accel_activate, accel_quark, closure, FALSE);
+
+ /* and notify */
+ g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+}
+
+static gboolean
+accel_group_disconnect_closure (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GClosure *closure)
+{
+ gchar *accel_name;
+ GQuark accel_quark;
+ GSList *clist , *slist;
+ gboolean removed_some = FALSE;
+
+ accel_name = gtk_accelerator_name (accel_key, accel_mods);
+ accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+
+ clist = quick_accel_remove (accel_group, accel_key, accel_mods);
+ if (!clist)
+ return FALSE;
- /* prematurely abort if the group/entry is already locked
- */
- if (accel_group->lock_count > 0)
- return;
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry && entry->accel_flags & GTK_ACCEL_LOCKED)
- return;
-
- /* make sure our structures stay alive
- */
g_object_ref (accel_group);
- g_object_ref (object);
-
- /* remove an existing entry
- */
- if (entry)
- g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
- accel_group,
- gdk_keyval_to_lower (accel_key),
- accel_mods & accel_group->modifier_mask);
-
- /* abort if the entry still exists
- */
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry)
- {
- g_object_unref (accel_group);
- g_object_unref (object);
-
- return;
- }
-
- /* collect accel groups and remove existing entries
- */
- attach_objects = accel_group->attach_objects;
- groups = NULL;
- for (attach_objects = accel_group->attach_objects; attach_objects; attach_objects = attach_objects->next)
- {
- GSList *tmp_groups;
-
- tmp_groups = g_object_get_qdata (attach_objects->data, accel_groups_key_id);
- while (tmp_groups)
- {
- groups = g_slist_prepend (groups, tmp_groups->data);
- g_object_ref (tmp_groups->data);
- tmp_groups = tmp_groups->next;
- }
- }
- for (slist = groups; slist; slist = slist->next)
- {
- GtkAccelGroup *tmp_group;
-
- tmp_group = slist->data;
-
- /* we only remove the accelerator if neccessary
- */
- if (tmp_group->lock_count == 0)
- {
- entry = gtk_accel_group_lookup (tmp_group, accel_key, accel_mods);
- if (entry && !(entry->accel_flags & GTK_ACCEL_LOCKED))
- g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
- tmp_group,
- gdk_keyval_to_lower (accel_key),
- accel_mods & tmp_group->modifier_mask);
- }
- g_object_unref (tmp_group);
- }
- g_slist_free (groups);
-
- /* now install the new accelerator
- */
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (!entry)
- g_signal_emit (object, add_accelerator_signal_id, 0,
- accel_signal_id,
- accel_group,
- gdk_keyval_to_lower (accel_key),
- accel_mods & accel_group->modifier_mask,
- accel_flags & GTK_ACCEL_MASK);
-
- /* and release the structures again
- */
+
+ for (slist = clist; slist; slist = slist->next)
+ if (!closure || slist->data == (gpointer) closure)
+ {
+ g_signal_handlers_disconnect_matched (accel_group, G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_ID,
+ signal_accel_activate, 0,
+ slist->data, NULL, NULL);
+ /* and notify */
+ g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, slist->data);
+
+ /* remove quick_accel_add() ref_count */
+ g_closure_unref (slist->data);
+
+ removed_some = TRUE;
+ }
+ g_slist_free (clist);
+
g_object_unref (accel_group);
- g_object_unref (object);
+
+ return removed_some;
}
-static void
-gtk_accel_group_delete_entries (GSList *entries)
+/**
+ * gtk_accel_group_disconnect
+ * @accel_group: the ccelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @returns: %TRUE if there was an accelerator which could be removed, %FALSE otherwise
+ *
+ * Remove an accelerator previously installed through
+ * gtk_accel_group_connect().
+ */
+gboolean
+gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods)
{
- GSList *slist;
-
- /* we remove all entries of this object the hard
- * way (i.e. without signal emission).
- */
- for (slist = entries; slist; slist = slist->next)
- {
- GtkAccelEntry *entry;
-
- entry = slist->data;
-
- g_hash_table_remove (accel_entry_hash_table, entry);
- g_object_unref (entry->accel_group);
- g_chunk_free (entry, accel_entries_mem_chunk);
- }
- g_slist_free (entries);
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ return accel_group_disconnect_closure (accel_group, accel_key, accel_mods, NULL);
}
-void
-gtk_accel_group_handle_add (GObject *object,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags)
+GtkAccelGroupEntry*
+gtk_accel_group_query (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ guint *n_entries)
{
- GtkAccelEntry *entry;
-
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
- g_return_if_fail (accel_signal_id > 0);
+ GtkAccelGroupEntry *entries;
+ guint n;
- if (!gtk_accelerator_valid (accel_key, accel_mods))
- return;
-
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (!entry)
- {
- GSList *slist;
-
- g_object_ref (accel_group);
-
- entry = g_chunk_new (GtkAccelEntry, accel_entries_mem_chunk);
- entry->accel_group = accel_group;
- entry->accelerator_key = gdk_keyval_to_lower (accel_key);
- entry->accelerator_mods = accel_mods & accel_group->modifier_mask;
- entry->accel_flags = accel_flags & GTK_ACCEL_MASK;
- entry->object = object;
- entry->signal_id = accel_signal_id;
-
- g_hash_table_insert (accel_entry_hash_table, entry, entry);
-
- slist = g_object_steal_qdata (object, accel_entries_key_id);
- slist = g_slist_prepend (slist, entry);
- g_object_set_qdata_full (object, accel_entries_key_id, slist,
- (GDestroyNotify) gtk_accel_group_delete_entries);
- }
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+ entries = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+
+ if (n_entries)
+ *n_entries = entries ? n : 0;
+
+ return entries;
}
-/**
- * gtk_accel_group_remove:
- * @accel_group: a #GtkAccelGroup
- * @accel_key: accelerator keyval
- * @accel_mods: accelerator modifiers
- * @object: object the accelerator activates
- *
- * Removes an accelerator. The @accel_key, @accel_mods, and @object
- * arguments are the same ones used to add the accelerator
- * with gtk_accel_group_add().
- *
- **/
-void
-gtk_accel_group_remove (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GObject *object)
+static gboolean
+find_accel_closure (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data)
{
- GtkAccelEntry *entry;
- guint remove_accelerator_signal_id = 0;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
- g_return_if_fail (G_IS_OBJECT (object));
-
- /* check for required signals in the objects branch
- */
- remove_accelerator_signal_id = g_signal_lookup ("remove-accelerator", G_OBJECT_TYPE (object));
- if (!remove_accelerator_signal_id)
- {
- g_warning ("gtk_accel_group_remove(): could not find signal \"%s\""
- "in the `%s' class ancestry",
- "remove-accelerator",
- g_type_name (G_OBJECT_TYPE (object)));
- return;
- }
-
- /* prematurely abort if the entry is locked
- */
- if (accel_group->lock_count > 0)
- return;
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (!entry ||
- entry->accel_flags & GTK_ACCEL_LOCKED)
- return;
- if (entry->object != object)
- {
- g_warning ("gtk_accel_group_remove(): invalid object reference for accel-group entry");
- return;
- }
-
- /* make sure our structures stay alive
- */
- g_object_ref (accel_group);
- g_object_ref (object);
-
- /* remove the entry
- */
- g_signal_emit (entry->object, remove_accelerator_signal_id, 0,
- accel_group,
- gdk_keyval_to_lower (accel_key),
- accel_mods & accel_group->modifier_mask);
-
- /* and release the structures again
- */
- g_object_unref (accel_group);
- g_object_unref (object);
+ return data == (gpointer) closure;
}
-void
-gtk_accel_group_handle_remove (GObject *object,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
+gboolean
+gtk_accel_groups_disconnect_closure (GClosure *closure)
{
- GtkAccelEntry *entry;
-
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (GTK_IS_ACCEL_GROUP(accel_group));
-
- entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
- if (entry)
+ GtkAccelGroup *group;
+
+ g_return_val_if_fail (closure != NULL, FALSE);
+
+ group = gtk_accel_group_from_accel_closure (closure);
+ if (group)
{
- if (entry->object == object)
+ GtkAccelKey *key = gtk_accel_group_find (group, find_accel_closure, closure);
+
+ /* sigh, not finding the key can unexpectedly happen if someone disposes
+ * accel groups. that's highly recommended to _not_ do though.
+ */
+ if (key)
{
- GSList *slist;
-
- g_hash_table_remove (accel_entry_hash_table, entry);
-
- slist = g_object_steal_qdata (object, accel_entries_key_id);
- if (slist)
- {
- slist = g_slist_remove (slist, entry);
- if (slist)
- g_object_set_qdata_full (object, accel_entries_key_id, slist,
- (GDestroyNotify) gtk_accel_group_delete_entries);
-
- g_object_unref (accel_group);
-
- g_chunk_free (entry, accel_entries_mem_chunk);
- }
+ accel_group_disconnect_closure (group, key->accel_key, key->accel_mods, closure);
+ return TRUE;
}
- else
- g_warning ("gtk_accel_group_handle_remove(): invalid object reference for accel-group entry");
}
- else
- g_warning ("gtk_accel_group_handle_remove(): attempt to remove unexisting accel-group entry");
+ return FALSE;
}
-guint
-gtk_accel_group_create_add (GType class_type,
- GSignalFlags signal_flags,
- guint handler_offset)
+GtkAccelGroup*
+gtk_accel_group_from_accel_closure (GClosure *closure)
{
- g_return_val_if_fail (G_TYPE_IS_OBJECT (class_type), 0);
-
- return g_signal_new ("add-accelerator",
- class_type,
- signal_flags,
- handler_offset,
- (GSignalAccumulator) NULL, NULL,
- gtk_marshal_VOID__UINT_OBJECT_UINT_FLAGS_FLAGS,
- G_TYPE_NONE, 5,
- G_TYPE_UINT,
- GTK_TYPE_ACCEL_GROUP,
- G_TYPE_UINT,
- GDK_TYPE_MODIFIER_TYPE,
- GTK_TYPE_ACCEL_FLAGS);
+ guint i;
+
+ g_return_val_if_fail (closure != NULL, NULL);
+
+ /* a few remarks on wat we do here. in general, we need a way to back-lookup
+ * accel_groups from closures that are being used in accel groups. this could
+ * be done e.g via a hashtable. it is however cheaper (memory wise) to just
+ * store a NOP notifier on the closure itself that contains the accel group
+ * as data which, besides needing to peek a bit at closure internals, works
+ * just as good.
+ */
+ for (i = 0; i < G_CLOSURE_N_NOTIFIERS (closure); i++)
+ if (closure->notifiers[i].notify == accel_tag_func)
+ return closure->notifiers[i].data;
+
+ return NULL;
}
-guint
-gtk_accel_group_create_remove (GType class_type,
- GSignalFlags signal_flags,
- guint handler_offset)
+gboolean
+_gtk_accel_group_activate (GtkAccelGroup *accel_group,
+ GQuark accel_quark,
+ GObject *acceleratable,
+ guint accel_key,
+ GdkModifierType accel_mods)
{
- g_return_val_if_fail (G_TYPE_IS_OBJECT (class_type), 0);
-
- return g_signal_new ("remove-accelerator",
- class_type,
- signal_flags,
- handler_offset,
- (GSignalAccumulator) NULL, NULL,
- gtk_marshal_VOID__OBJECT_UINT_FLAGS,
- G_TYPE_NONE, 3,
- GTK_TYPE_ACCEL_GROUP,
- G_TYPE_UINT,
- GDK_TYPE_MODIFIER_TYPE);
+ gboolean was_handled;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ was_handled = FALSE;
+ g_signal_emit (accel_group, signal_accel_activate, accel_quark,
+ acceleratable, accel_key, accel_mods, &was_handled);
+
+ return was_handled;
}
-GSList*
-gtk_accel_groups_from_object (GObject *object)
+/**
+ * gtk_accel_groups_activate:
+ * @acceleratable: usually a #GtkWindow
+ * @accel_key: accelerator keyval from a key event
+ * @accel_mods: keyboard state mask from a key event
+ * @returns: %TRUE if the accelerator was handled, %FALSE otherwise
+ *
+ * Finds the first accelerator in any #GtkAccelGroup attached
+ * to @acceleratable that matches @accel_key and @accel_mods, and
+ * activates that accelerator.
+ * If an accelerator was activated and handled this keypress, %TRUE
+ * is returned.
+ */
+gboolean
+gtk_accel_groups_activate (GObject *acceleratable,
+ guint accel_key,
+ GdkModifierType accel_mods)
{
- g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (G_IS_OBJECT (acceleratable), FALSE);
- return g_object_get_qdata (object, accel_groups_key_id);
-}
+ if (gtk_accelerator_valid (accel_key, accel_mods))
+ {
+ gchar *accel_name;
+ GQuark accel_quark;
+ GSList *slist;
-GSList*
-gtk_accel_group_entries_from_object (GObject *object)
-{
- g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+ accel_name = gtk_accelerator_name (accel_key, accel_mods);
+ accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+
+ for (slist = gtk_accel_groups_from_acceleratable (acceleratable); slist; slist = slist->next)
+ if (_gtk_accel_group_activate (slist->data, accel_quark, acceleratable, accel_key, accel_mods))
+ return TRUE;
+ }
- return g_object_get_qdata (object, accel_entries_key_id);
+ return FALSE;
}
/**
- * gtk_accelerator_valid:
- * @keyval: a GDK keyval
+ * gtk_accelerator_valid
+ * @keyval: a GDK keyval
* @modifiers: modifier mask
+ * @returns: %TRUE if the accelerator is valid
*
* Determines whether a given keyval and modifier mask constitute
* a valid keyboard accelerator. For example, the GDK_a keyval
* plus GDK_CONTROL_MASK is valid - this is a "Ctrl+a" accelerator.
- * But you can't use the NumLock key as an accelerator.
- *
- * Return value: %TRUE if the accelerator is valid
- **/
+ * But by default (see gtk_accelerator_set_default_mod_mask()) you
+ * cannot use the NumLock key as an accelerator modifier.
+ */
gboolean
gtk_accelerator_valid (guint keyval,
GdkModifierType modifiers)
@@ -1018,10 +784,10 @@ is_release (const gchar *string)
}
/**
- * gtk_accelerator_parse:
- * @accelerator: string representing an accelerator
- * @accelerator_key: return location for accelerator keyval
- * @accelerator_mods: return location for accelerator mod mask
+ * gtk_accelerator_parse
+ * @accelerator: string representing an accelerator
+ * @accelerator_key: return location for accelerator keyval
+ * @accelerator_mods: return location for accelerator modifier mask
*
* Parses a string representing an accelerator. The
* format looks like "<Control>a" or "<Shift><Alt>F1" or
@@ -1031,11 +797,11 @@ is_release (const gchar *string)
*
* If the parse fails, @accelerator_key and @accelerator_mods will
* be set to 0 (zero).
- **/
+ */
void
-gtk_accelerator_parse (const gchar *accelerator,
- guint *accelerator_key,
- GdkModifierType*accelerator_mods)
+gtk_accelerator_parse (const gchar *accelerator,
+ guint *accelerator_key,
+ GdkModifierType *accelerator_mods)
{
guint keyval;
GdkModifierType mods;
@@ -1136,19 +902,18 @@ gtk_accelerator_parse (const gchar *accelerator,
}
/**
- * gtk_accelerator_name:
- * @accelerator_key: an accelerator keyval
- * @accelerator_mods: modifier mask
+ * gtk_accelerator_name
+ * @accelerator_key: accelerator keyval
+ * @accelerator_mods: accelerator modifier mask
+ * @returns: a newly allocated accelerator name
*
* Converts an accelerator keyval and modifier mask
* into a string parseable by gtk_accelerator_parse().
* For example, if you pass in GDK_q and GDK_CONTROL_MASK,
* this function returns "<Control>q".
*
- * The caller of this function must free the return value.
- *
- * Return value: the new accelerator name
- **/
+ * The caller of this function must free the returned string.
+ */
gchar*
gtk_accelerator_name (guint accelerator_key,
GdkModifierType accelerator_mods)
@@ -1240,18 +1005,17 @@ gtk_accelerator_name (guint accelerator_key,
}
/**
- * gtk_accelerator_set_default_mod_mask:
- * @default_mod_mask: a modifier mask
+ * gtk_accelerator_set_default_mod_mask
+ * @default_mod_mask: accelerator modifier mask
*
* Sets the modifiers that will be considered significant for keyboard
* accelerators. The default mod mask is #GDK_CONTROL_MASK |
* #GDK_SHIFT_MASK | #GDK_MOD1_MASK, that is, Control, Shift, and Alt.
- * Other modifiers will be ignored by #GtkAccelGroup.
+ * Other modifiers will by default be ignored by #GtkAccelGroup.
*
* The default mod mask should be changed on application startup,
- * before creating any accelerator groups.
- *
- **/
+ * before using any accelerator groups.
+ */
void
gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask)
{
@@ -1259,12 +1023,11 @@ gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask)
}
/**
- * gtk_accelerator_get_default_mod_mask:
+ * gtk_accelerator_get_default_mod_mask
+ * @returns: the default accelerator modifier mask
*
* Gets the value set by gtk_accelerator_set_default_mod_mask().
- *
- * Return value: the default modifier mask.
- **/
+ */
guint
gtk_accelerator_get_default_mod_mask (void)
{
diff --git a/gtk/gtkaccelgroup.h b/gtk/gtkaccelgroup.h
index d3e8d1fb48..5fca1a33b3 100644
--- a/gtk/gtkaccelgroup.h
+++ b/gtk/gtkaccelgroup.h
@@ -1,8 +1,5 @@
/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GtkAccelGroup: Accelerator manager for GtkObjects.
- * Copyright (C) 1998 Tim Janik
+ * Copyright (C) 1998, 2001 Tim Janik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -32,13 +29,12 @@
#include <gdk/gdk.h>
-#include <gtk/gtkobject.h>
#include <gtk/gtkenums.h>
-
G_BEGIN_DECLS
+/* --- type macros --- */
#define GTK_TYPE_ACCEL_GROUP (gtk_accel_group_get_type ())
#define GTK_ACCEL_GROUP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ACCEL_GROUP, GtkAccelGroup))
#define GTK_ACCEL_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
@@ -47,136 +43,113 @@ G_BEGIN_DECLS
#define GTK_ACCEL_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
-typedef struct _GtkAccelGroup GtkAccelGroup;
-typedef struct _GtkAccelGroupClass GtkAccelGroupClass;
-typedef struct _GtkAccelEntry GtkAccelEntry;
-
+/* --- accel flags --- */
typedef enum
{
- /* should the accelerator appear in
- * the widget's display?
- */
- GTK_ACCEL_VISIBLE = 1 << 0,
- /* should the signal associated with
- * this accelerator be also visible?
- */
- GTK_ACCEL_SIGNAL_VISIBLE = 1 << 1,
- /* may the accelerator be removed
- * again?
- */
- GTK_ACCEL_LOCKED = 1 << 2,
+ GTK_ACCEL_VISIBLE = 1 << 0, /* display in GtkAccelLabel? */
+ GTK_ACCEL_LOCKED = 1 << 1, /* is it removable? */
GTK_ACCEL_MASK = 0x07
} GtkAccelFlags;
+
+/* --- typedefs & structures --- */
+typedef struct _GtkAccelGroup GtkAccelGroup;
+typedef struct _GtkAccelGroupClass GtkAccelGroupClass;
+typedef struct _GtkAccelKey GtkAccelKey;
+typedef struct _GtkAccelGroupEntry GtkAccelGroupEntry;
+typedef gboolean (*GtkAccelGroupActivate) (GtkAccelGroup *accel_group,
+ GObject *acceleratable,
+ guint keyval,
+ GdkModifierType modifier);
struct _GtkAccelGroup
{
- GObject parent;
- guint lock_count;
- GdkModifierType modifier_mask;
- GSList *attach_objects;
+ GObject parent;
+ guint lock_count;
+ GdkModifierType modifier_mask;
+ GSList *acceleratables;
+ guint n_accels;
+ GtkAccelGroupEntry *priv_accels;
};
-
struct _GtkAccelGroupClass
{
GObjectClass parent_class;
-};
-struct _GtkAccelEntry
+ void (*accel_changed) (GtkAccelGroup *accel_group,
+ guint keyval,
+ GdkModifierType modifier,
+ GClosure *accel_closure);
+};
+struct _GtkAccelKey
{
- /* key portion
- */
- GtkAccelGroup *accel_group;
- guint accelerator_key;
- GdkModifierType accelerator_mods;
-
- GtkAccelFlags accel_flags;
- GObject *object;
- guint signal_id;
+ guint accel_key;
+ GdkModifierType accel_mods;
+ guint accel_flags : 16;
};
-/* Accelerators
- */
-gboolean gtk_accelerator_valid (guint keyval,
- GdkModifierType modifiers) G_GNUC_CONST;
-void gtk_accelerator_parse (const gchar *accelerator,
- guint *accelerator_key,
- GdkModifierType *accelerator_mods);
-gchar* gtk_accelerator_name (guint accelerator_key,
- GdkModifierType accelerator_mods);
-void gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask);
-guint gtk_accelerator_get_default_mod_mask (void);
-
-
-/* Accelerator Groups
- */
+/* -- Accelerator Groups --- */
GType gtk_accel_group_get_type (void);
GtkAccelGroup* gtk_accel_group_new (void);
-GtkAccelGroup* gtk_accel_group_get_default (void);
-GtkAccelGroup* gtk_accel_group_ref (GtkAccelGroup *accel_group);
-void gtk_accel_group_unref (GtkAccelGroup *accel_group);
void gtk_accel_group_lock (GtkAccelGroup *accel_group);
void gtk_accel_group_unlock (GtkAccelGroup *accel_group);
-gboolean gtk_accel_groups_activate (GObject *object,
+void gtk_accel_group_connect (GtkAccelGroup *accel_group,
guint accel_key,
- GdkModifierType accel_mods);
-
-/* internal functions
- */
-gboolean gtk_accel_group_activate (GtkAccelGroup *accel_group,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure,
+ GQuark accel_path_quark);
+gboolean gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
guint accel_key,
GdkModifierType accel_mods);
-void gtk_accel_group_attach (GtkAccelGroup *accel_group,
+gboolean gtk_accel_groups_disconnect_closure (GClosure *closure);
+
+
+/* --- GtkActivatable glue --- */
+void _gtk_accel_group_attach (GtkAccelGroup *accel_group,
GObject *object);
-void gtk_accel_group_detach (GtkAccelGroup *accel_group,
+void _gtk_accel_group_detach (GtkAccelGroup *accel_group,
GObject *object);
-
-/* Accelerator Group Entries (internal)
- */
-GtkAccelEntry* gtk_accel_group_get_entry (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods);
-void gtk_accel_group_lock_entry (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods);
-void gtk_accel_group_unlock_entry (GtkAccelGroup *accel_group,
+gboolean gtk_accel_groups_activate (GObject *acceleratable,
guint accel_key,
GdkModifierType accel_mods);
-void gtk_accel_group_add (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags,
- GObject *object,
- const gchar *accel_signal);
-void gtk_accel_group_remove (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GObject *object);
+GSList* gtk_accel_groups_from_acceleratable (GObject *object);
+GtkAccelKey* gtk_accel_group_find (GtkAccelGroup *accel_group,
+ gboolean (*find_func) (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data),
+ gpointer data);
+GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure *closure);
-/* Accelerator Signals (internal)
- */
-void gtk_accel_group_handle_add (GObject *object,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
+
+/* --- Accelerators--- */
+gboolean gtk_accelerator_valid (guint keyval,
+ GdkModifierType modifiers) G_GNUC_CONST;
+void gtk_accelerator_parse (const gchar *accelerator,
+ guint *accelerator_key,
+ GdkModifierType *accelerator_mods);
+gchar* gtk_accelerator_name (guint accelerator_key,
+ GdkModifierType accelerator_mods);
+void gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask);
+guint gtk_accelerator_get_default_mod_mask (void);
+
+
+/* --- internal --- */
+GtkAccelGroupEntry* gtk_accel_group_query (GtkAccelGroup *accel_group,
guint accel_key,
GdkModifierType accel_mods,
- GtkAccelFlags accel_flags);
-void gtk_accel_group_handle_remove (GObject *object,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods);
-guint gtk_accel_group_create_add (GType class_type,
- GSignalFlags signal_flags,
- guint handler_offset);
-guint gtk_accel_group_create_remove (GType class_type,
- GSignalFlags signal_flags,
- guint handler_offset);
-
-/* Miscellaneous (internal)
- */
-GSList* gtk_accel_groups_from_object (GObject *object);
-GSList* gtk_accel_group_entries_from_object (GObject *object);
+ guint *n_entries);
+struct _GtkAccelGroupEntry
+{
+ GtkAccelKey key;
+ GClosure *closure;
+ GQuark accel_path_quark;
+};
+
+#ifndef GTK_DISABLE_DEPRECATED
+#define gtk_accel_group_ref g_object_ref
+#define gtk_accel_group_unref g_object_unref
+#endif /* GTK_DISABLE_DEPRECATED */
G_END_DECLS
diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c
index 82b4f35beb..bee1060bd8 100644
--- a/gtk/gtkaccellabel.c
+++ b/gtk/gtkaccellabel.c
@@ -26,17 +26,19 @@
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-
-#include <string.h>
-#include <ctype.h>
+#include "gtkaccellabel.h"
+#include "gtkaccelmap.h"
#include "gtkmain.h"
#include "gtksignal.h"
-#include "gtkaccellabel.h"
#include "gtkintl.h"
+#include <string.h>
+#include <ctype.h>
+
enum {
PROP_0,
- PROP_ACCEL_OBJECT
+ PROP_ACCEL_CLOSURE,
+ PROP_ACCEL_WIDGET
};
static void gtk_accel_label_class_init (GtkAccelLabelClass *klass);
@@ -90,33 +92,17 @@ static void
gtk_accel_label_class_init (GtkAccelLabelClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkMiscClass *misc_class;
- GtkLabelClass *label_class;
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
accel_label_class = class;
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
- misc_class = (GtkMiscClass*) class;
- label_class = (GtkLabelClass*) class;
-
- parent_class = gtk_type_class (GTK_TYPE_LABEL);
+ parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_accel_label_finalize;
gobject_class->set_property = gtk_accel_label_set_property;
gobject_class->get_property = gtk_accel_label_get_property;
object_class->destroy = gtk_accel_label_destroy;
-
- g_object_class_install_property (G_OBJECT_CLASS(object_class),
- PROP_ACCEL_OBJECT,
- g_param_spec_object ("accel_object",
- _("Accelerator object"),
- _("The object monitored by this accelerator label"),
- G_TYPE_OBJECT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
widget_class->size_request = gtk_accel_label_size_request;
widget_class->expose_event = gtk_accel_label_expose_event;
@@ -129,6 +115,21 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
class->mod_separator = g_strdup ("+");
class->accel_seperator = g_strdup (" / ");
class->latin1_to_char = TRUE;
+
+ g_object_class_install_property (G_OBJECT_CLASS (object_class),
+ PROP_ACCEL_CLOSURE,
+ g_param_spec_object ("accel_closure",
+ _("Accelerator Closure"),
+ _("The closure to be monitored for accelerator changes"),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+ g_object_class_install_property (G_OBJECT_CLASS (object_class),
+ PROP_ACCEL_WIDGET,
+ g_param_spec_object ("accel_widget",
+ _("Accelerator Widget"),
+ _("The widget to be monitored for accelerator changes"),
+ GTK_TYPE_WIDGET,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
}
static void
@@ -143,8 +144,11 @@ gtk_accel_label_set_property (GObject *object,
switch (prop_id)
{
- case PROP_ACCEL_OBJECT:
- gtk_accel_label_set_accel_object (accel_label, g_value_get_object (value));
+ case PROP_ACCEL_CLOSURE:
+ gtk_accel_label_set_accel_closure (accel_label, g_value_get_boxed (value));
+ break;
+ case PROP_ACCEL_WIDGET:
+ gtk_accel_label_set_accel_widget (accel_label, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -152,10 +156,11 @@ gtk_accel_label_set_property (GObject *object,
}
}
-static void gtk_accel_label_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+static void
+gtk_accel_label_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
GtkAccelLabel *accel_label;
@@ -163,8 +168,11 @@ static void gtk_accel_label_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ACCEL_OBJECT:
- g_value_set_object (value, accel_label->accel_object);
+ case PROP_ACCEL_CLOSURE:
+ g_value_set_boxed (value, accel_label->accel_closure);
+ break;
+ case PROP_ACCEL_WIDGET:
+ g_value_set_object (value, accel_label->accel_widget);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -177,7 +185,9 @@ gtk_accel_label_init (GtkAccelLabel *accel_label)
{
accel_label->queue_id = 0;
accel_label->accel_padding = 3;
- accel_label->accel_object = NULL;
+ accel_label->accel_widget = NULL;
+ accel_label->accel_closure = NULL;
+ accel_label->accel_group = NULL;
accel_label->accel_string = NULL;
gtk_accel_label_refetch (accel_label);
@@ -206,7 +216,8 @@ gtk_accel_label_destroy (GtkObject *object)
accel_label = GTK_ACCEL_LABEL (object);
- gtk_accel_label_set_accel_object (accel_label, NULL);
+ gtk_accel_label_set_accel_widget (accel_label, NULL);
+ gtk_accel_label_set_accel_closure (accel_label, NULL);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
@@ -214,33 +225,34 @@ gtk_accel_label_destroy (GtkObject *object)
static void
gtk_accel_label_finalize (GObject *object)
{
- GtkAccelLabel *accel_label;
-
- g_return_if_fail (GTK_IS_ACCEL_LABEL (object));
-
- accel_label = GTK_ACCEL_LABEL (object);
-
+ GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
+
+ if (accel_label->queue_id)
+ {
+ gtk_idle_remove (accel_label->queue_id);
+ accel_label->queue_id = 0;
+ }
g_free (accel_label->accel_string);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/**
- * gtk_accel_label_get_accel_object:
+ * gtk_accel_label_get_accel_widget:
* @accel_label: a #GtkAccelLabel
*
* Fetches the widget monitored by this accelerator label. See
- * gtk_accel_label_set_accel_object().
+ * gtk_accel_label_set_accel_widget().
*
* Return value: the object monitored by the accelerator label,
* or %NULL.
**/
-GObject *
-gtk_accel_label_get_accel_object (GtkAccelLabel *accel_label)
+GtkWidget*
+gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
{
g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
- return accel_label->accel_object;
+ return accel_label->accel_widget;
}
guint
@@ -337,6 +349,55 @@ gtk_accel_label_expose_event (GtkWidget *widget,
}
static void
+refetch_widget_accel_closure (GtkAccelLabel *accel_label)
+{
+ GSList *slist;
+
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+ g_return_if_fail (GTK_IS_WIDGET (accel_label->accel_widget));
+
+ for (slist = _gtk_widget_get_accel_closures (accel_label->accel_widget); slist; slist = slist->next)
+ if (gtk_accel_group_from_accel_closure (slist->data))
+ {
+ /* we just take the first correctly used closure */
+ gtk_accel_label_set_accel_closure (accel_label, slist->data);
+ return;
+ }
+ gtk_accel_label_set_accel_closure (accel_label, NULL);
+}
+
+void
+gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+ GtkWidget *accel_widget)
+{
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+ if (accel_widget)
+ g_return_if_fail (GTK_IS_WIDGET (accel_widget));
+
+ if (accel_widget != accel_label->accel_widget)
+ {
+ if (accel_label->accel_widget)
+ {
+ gtk_accel_label_set_accel_closure (accel_label, NULL);
+ g_signal_handlers_disconnect_by_func (accel_label->accel_widget,
+ G_CALLBACK (refetch_widget_accel_closure),
+ accel_label);
+ g_object_unref (accel_label->accel_widget);
+ }
+ accel_label->accel_widget = accel_widget;
+ if (accel_label->accel_widget)
+ {
+ g_object_ref (accel_label->accel_widget);
+ g_signal_connect_object (accel_label->accel_widget, "accel_closures_changed",
+ G_CALLBACK (refetch_widget_accel_closure),
+ accel_label, G_CONNECT_SWAPPED);
+ refetch_widget_accel_closure (accel_label);
+ }
+ g_object_notify (G_OBJECT (accel_label), "accel_widget");
+ }
+}
+
+static void
gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label)
{
g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
@@ -347,45 +408,46 @@ gtk_accel_label_queue_refetch (GtkAccelLabel *accel_label)
accel_label);
}
+static void
+check_accel_changed (GtkAccelGroup *accel_group,
+ guint keyval,
+ GdkModifierType modifier,
+ GClosure *accel_closure,
+ GtkAccelLabel *accel_label)
+{
+ if (accel_closure == accel_label->accel_closure)
+ gtk_accel_label_queue_refetch (accel_label);
+}
+
void
-gtk_accel_label_set_accel_object (GtkAccelLabel *accel_label,
- GObject *accel_object)
+gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+ GClosure *accel_closure)
{
g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
- g_return_if_fail (accel_object == NULL || G_IS_OBJECT (accel_object));
-
- if (accel_object != accel_label->accel_object)
+ if (accel_closure)
+ g_return_if_fail (gtk_accel_group_from_accel_closure (accel_closure) != NULL);
+
+ if (accel_closure != accel_label->accel_closure)
{
- if (accel_label->accel_object)
+ if (accel_label->accel_closure)
{
- g_signal_handlers_disconnect_by_func (accel_label->accel_object,
- G_CALLBACK (gtk_accel_label_queue_refetch),
- accel_object);
- g_object_unref (accel_label->accel_object);
+ g_signal_handlers_disconnect_by_func (accel_label->accel_group,
+ G_CALLBACK (check_accel_changed),
+ accel_label);
+ accel_label->accel_group = NULL;
+ g_closure_unref (accel_label->accel_closure);
}
- if (accel_label->queue_id)
+ accel_label->accel_closure = accel_closure;
+ if (accel_label->accel_closure)
{
- gtk_idle_remove (accel_label->queue_id);
- accel_label->queue_id = 0;
+ g_closure_ref (accel_label->accel_closure);
+ accel_label->accel_group = gtk_accel_group_from_accel_closure (accel_closure);
+ g_signal_connect_object (accel_label->accel_group, "accel_changed",
+ G_CALLBACK (check_accel_changed),
+ accel_label, 0);
}
- accel_label->accel_object = accel_object;
- if (accel_label->accel_object)
- {
- g_object_ref (accel_label->accel_object);
- g_signal_connect_object (accel_label->accel_object,
- "add-accelerator",
- G_CALLBACK (gtk_accel_label_queue_refetch),
- accel_label,
- G_CONNECT_AFTER | G_CONNECT_SWAPPED);
- g_signal_connect_object (accel_label->accel_object,
- "remove-accelerator",
- G_CALLBACK (gtk_accel_label_queue_refetch),
- accel_label,
- G_CONNECT_AFTER | G_CONNECT_SWAPPED);
- }
- gtk_accel_label_refetch (accel_label);
-
- g_object_notify (G_OBJECT (accel_label), "accel_object");
+ gtk_accel_label_queue_refetch (accel_label);
+ g_object_notify (G_OBJECT (accel_label), "accel_closure");
}
}
@@ -401,107 +463,106 @@ gtk_accel_label_refetch_idle (GtkAccelLabel *accel_label)
return retval;
}
+static gboolean
+find_accel (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data)
+{
+ return data == (gpointer) closure;
+}
+
gboolean
gtk_accel_label_refetch (GtkAccelLabel *accel_label)
{
GtkAccelLabelClass *class;
+ gchar *utf8;
g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), FALSE);
class = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
-
+
g_free (accel_label->accel_string);
accel_label->accel_string = NULL;
-
- if (accel_label->accel_object)
+
+ if (accel_label->accel_closure)
{
- GtkAccelEntry *entry = NULL;
- GSList *slist;
-
- slist = gtk_accel_group_entries_from_object (accel_label->accel_object);
- for (; slist; slist = slist->next)
+ GtkAccelKey *key = gtk_accel_group_find (accel_label->accel_group, find_accel, accel_label->accel_closure);
+
+ if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
{
- entry = slist->data;
- if (entry->accel_flags & GTK_ACCEL_VISIBLE)
+ GString *gstring;
+ gboolean seen_mod = FALSE;
+
+ gstring = g_string_new (accel_label->accel_string);
+ g_string_append (gstring, gstring->len ? class->accel_seperator : " ");
+
+ if (key->accel_mods & GDK_SHIFT_MASK)
{
- GString *gstring;
- gboolean had_mod;
-
- gstring = g_string_new (accel_label->accel_string);
- if (gstring->len)
- g_string_append (gstring, class->accel_seperator);
- else
- g_string_append (gstring, " ");
-
- if (entry->accel_flags & GTK_ACCEL_SIGNAL_VISIBLE)
- {
- g_string_append (gstring, class->signal_quote1);
- g_string_append (gstring, gtk_signal_name (entry->signal_id));
- g_string_append (gstring, class->signal_quote2);
- }
-
- had_mod = FALSE;
- if (entry->accelerator_mods & GDK_SHIFT_MASK)
- {
- g_string_append (gstring, class->mod_name_shift);
- had_mod = TRUE;
- }
- if (entry->accelerator_mods & GDK_CONTROL_MASK)
- {
- if (had_mod)
- g_string_append (gstring, class->mod_separator);
- g_string_append (gstring, class->mod_name_control);
- had_mod = TRUE;
- }
- if (entry->accelerator_mods & GDK_MOD1_MASK)
- {
- if (had_mod)
- g_string_append (gstring, class->mod_separator);
- g_string_append (gstring, class->mod_name_alt);
- had_mod = TRUE;
- }
-
- if (had_mod)
+ g_string_append (gstring, class->mod_name_shift);
+ seen_mod = TRUE;
+ }
+ if (key->accel_mods & GDK_CONTROL_MASK)
+ {
+ if (seen_mod)
g_string_append (gstring, class->mod_separator);
- if (entry->accelerator_key < 0x80 ||
- (entry->accelerator_key > 0x80 &&
- entry->accelerator_key <= 0xff &&
- class->latin1_to_char))
- {
- switch (entry->accelerator_key)
- {
- case ' ':
- g_string_append (gstring, "Space");
- break;
- case '\\':
- g_string_append (gstring, "Backslash");
- break;
- default:
- g_string_append_c (gstring, toupper (entry->accelerator_key));
- break;
- }
- }
- else
+ g_string_append (gstring, class->mod_name_control);
+ seen_mod = TRUE;
+ }
+ if (key->accel_mods & GDK_MOD1_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, class->mod_separator);
+ g_string_append (gstring, class->mod_name_alt);
+ seen_mod = TRUE;
+ }
+ if (seen_mod)
+ g_string_append (gstring, class->mod_separator);
+ if (key->accel_key < 0x80 ||
+ (key->accel_key > 0x80 &&
+ key->accel_key <= 0xff &&
+ class->latin1_to_char))
+ {
+ switch (key->accel_key)
{
- gchar *tmp;
-
- tmp = gtk_accelerator_name (entry->accelerator_key, 0);
- if (tmp[0] != 0 && tmp[1] == 0)
- tmp[0] = toupper (tmp[0]);
- g_string_append (gstring, tmp);
- g_free (tmp);
+ case ' ':
+ g_string_append (gstring, "Space");
+ break;
+ case '\\':
+ g_string_append (gstring, "Backslash");
+ break;
+ default:
+ g_string_append_c (gstring, toupper (key->accel_key));
+ break;
}
-
- g_free (accel_label->accel_string);
- accel_label->accel_string = gstring->str;
- g_string_free (gstring, FALSE);
}
+ else
+ {
+ gchar *tmp;
+
+ tmp = gtk_accelerator_name (key->accel_key, 0);
+ if (tmp[0] != 0 && tmp[1] == 0)
+ tmp[0] = toupper (tmp[0]);
+ g_string_append (gstring, tmp);
+ g_free (tmp);
+ }
+ g_free (accel_label->accel_string);
+ accel_label->accel_string = gstring->str;
+ g_string_free (gstring, FALSE);
}
+ if (!accel_label->accel_string)
+ accel_label->accel_string = g_strdup ("-/-");
}
-
+
if (!accel_label->accel_string)
accel_label->accel_string = g_strdup ("");
+ utf8 = g_locale_to_utf8 (accel_label->accel_string, -1, NULL, NULL, NULL);
+ if (utf8)
+ {
+ g_free (accel_label->accel_string);
+ accel_label->accel_string = utf8;
+ }
+
if (accel_label->queue_id)
{
gtk_idle_remove (accel_label->queue_id);
diff --git a/gtk/gtkaccellabel.h b/gtk/gtkaccellabel.h
index 5a9b779aac..89529e88d4 100644
--- a/gtk/gtkaccellabel.h
+++ b/gtk/gtkaccellabel.h
@@ -54,11 +54,13 @@ struct _GtkAccelLabel
{
GtkLabel label;
- guint queue_id;
- guint accel_padding;
- GObject *accel_object;
- gchar *accel_string;
- guint16 accel_string_width;
+ guint queue_id;
+ guint accel_padding;
+ GtkWidget *accel_widget;
+ GClosure *accel_closure;
+ GtkAccelGroup *accel_group;
+ gchar *accel_string;
+ guint16 accel_string_width;
};
struct _GtkAccelLabelClass
@@ -80,20 +82,15 @@ struct _GtkAccelLabelClass
#endif /* GTK_DISABLE_DEPRECATED */
GtkType gtk_accel_label_get_type (void) G_GNUC_CONST;
-GtkWidget *gtk_accel_label_new (const gchar *string);
-GObject *gtk_accel_label_get_accel_object (GtkAccelLabel *accel_label);
+GtkWidget* gtk_accel_label_new (const gchar *string);
+GtkWidget* gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label);
guint gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label);
-void gtk_accel_label_set_accel_object (GtkAccelLabel *accel_label,
- GObject *accel_object);
+void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+ GtkWidget *accel_widget);
+void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+ GClosure *closure);
gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label);
-#ifndef GTK_DISABLE_DEPRECATED
-#define gtk_accel_label_get_accel_widget(accel_label) \
- GTK_WIDGET(gtk_accel_label_get_accel_object(acel_label))
-#define gtk_accel_label_set_accel_widget(accel_label, accel_widget) \
- gtk_accel_label_set_accel_object((accel_label), G_OBJECT(accel_widget))
-#endif
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gtk/gtkaccelmap.c b/gtk/gtkaccelmap.c
new file mode 100644
index 0000000000..24dca7d5c3
--- /dev/null
+++ b/gtk/gtkaccelmap.c
@@ -0,0 +1,858 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gtkaccelmap.h"
+
+#include "gtkwindow.h" /* in lack of GtkAcceleratable */
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+/* --- structures --- */
+typedef struct {
+ const gchar *accel_path;
+ guint accel_key;
+ guint accel_mods;
+ guint std_accel_key;
+ guint std_accel_mods;
+ guint changed : 1;
+ GHookList *hooks;
+} AccelEntry;
+
+
+/* --- variables --- */
+static GHashTable *accel_entry_ht = NULL; /* accel_path -> AccelEntry */
+static GSList *accel_filters = NULL;
+
+
+/* --- functions --- */
+static guint
+accel_entry_hash (gconstpointer key)
+{
+ const AccelEntry *entry = key;
+
+ return g_str_hash (entry->accel_path);
+}
+
+static gboolean
+accel_entry_equal (gconstpointer key1,
+ gconstpointer key2)
+{
+ const AccelEntry *entry1 = key1;
+ const AccelEntry *entry2 = key2;
+
+ return g_str_equal (entry1->accel_path, entry2->accel_path);
+}
+
+static inline AccelEntry*
+accel_path_lookup (const gchar *accel_path)
+{
+ AccelEntry ekey;
+
+ ekey.accel_path = accel_path;
+
+ /* safety NULL check for return_if_fail()s */
+ return accel_path ? g_hash_table_lookup (accel_entry_ht, &ekey) : NULL;
+}
+
+void
+_gtk_accel_map_init (void)
+{
+ g_assert (accel_entry_ht == NULL);
+
+ accel_entry_ht = g_hash_table_new (accel_entry_hash, accel_entry_equal);
+}
+
+static gboolean
+gtk_accel_path_is_valid (const gchar *accel_path)
+{
+ gchar *p;
+
+ if (!accel_path || accel_path[0] != '<' ||
+ accel_path[1] == '<' || accel_path[1] == '>' || !accel_path[1])
+ return FALSE;
+ p = strchr (accel_path, '>');
+ if (!p || p[1] != '/')
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * gtk_accel_map_add_entry
+ * @accel_path: valid accelerator path
+ * @accel_key: the accelerator key
+ * @accel_mods: the accelerator modifiers
+ * @returns: the GQuark for the @accel_path (to ease local storage)
+ *
+ * Register a new accelerator with the global accelerator map.
+ * This function should only be called once per @accel_path
+ * with the canonical @accel_key and @accel_mods for this path.
+ * To change the accelerator during runtime programatically, use
+ * gtk_accel_map_change_entry().
+ * The accelerator path must consist of "<WINDOWTYPE>/Category1/Category2/.../Action",
+ * where WINDOWTYPE should be a unique application specifc identifier, that
+ * corresponds to the kind of window the accelerator is being used in, e.g. "Gimp-Image",
+ * "Abiword-Document" or "Gnumeric-Settings".
+ * The Category1/.../Action portion is most apropriately choosen by the action the
+ * accelerator triggers, i.e. for accelerators on menu items, choose the item's menu path,
+ * e.g. "File/Save As", "Image/View/Zoom" or "Edit/Select All".
+ * So a full valid accelerator path may look like:
+ * "<Gimp-Toolbox>/File/Dialogs/Tool Options...".
+ */
+GQuark
+gtk_accel_map_add_entry (const gchar *accel_path,
+ guint accel_key,
+ guint accel_mods)
+{
+ AccelEntry *entry;
+
+ g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), 0);
+
+ accel_mods &= gtk_accelerator_get_default_mod_mask ();
+
+ entry = accel_path_lookup (accel_path);
+ if (entry)
+ {
+ if (!entry->std_accel_key && !entry->std_accel_mods &&
+ (accel_key || accel_mods))
+ {
+ entry->std_accel_key = accel_key;
+ entry->std_accel_mods = accel_mods;
+ if (!entry->changed)
+ gtk_accel_map_change_entry (entry->accel_path, accel_key, accel_mods, TRUE);
+ }
+ }
+ else
+ {
+ entry = g_new0 (AccelEntry, 1);
+ entry->accel_path = g_quark_to_string (g_quark_from_string (accel_path));
+ entry->std_accel_key = accel_key;
+ entry->std_accel_mods = accel_mods;
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = FALSE;
+ g_hash_table_insert (accel_entry_ht, entry, entry);
+ }
+ return g_quark_try_string (entry->accel_path);
+}
+
+typedef struct {
+ GHook hook;
+ GtkAccelGroup *accel_group;
+} AccelHook;
+
+static void
+accel_hook_finalize (GHookList *hook_list,
+ GHook *hook)
+{
+ GDestroyNotify destroy = hook->destroy;
+ AccelHook *ahook = (AccelHook*) hook;
+
+ if (ahook->accel_group)
+ g_object_unref (ahook->accel_group);
+
+ if (destroy)
+ {
+ hook->destroy = NULL;
+ destroy (hook->data);
+ }
+}
+
+/**
+ * GtkAccelMapNotify
+ * @data: notifier user data
+ * @accel_path_quark: accelerator path (as #GQuark) which has just changed
+ * @accel_key: new accelerator key
+ * @accel_mods: new accelerator modifiers
+ * @accel_group: accelerator group of this notifier
+ * @old_accel_key: former accelerator key
+ * @old_accel_mods): former accelerator modifiers
+ *
+ * #GtkAccelMapNotify is the signature of user callbacks, installed via
+ * gtk_accel_map_add_notifier(). Once the accel path of the notifier changes,
+ * the notifier is invoked with this signature, where @accel_path_quark
+ * indicates the accel path that changed, and @data and @accel_group are
+ * the notifier's arguments as passed into gtk_accel_map_add_notifier().
+ */
+
+/**
+ * gtk_accel_map_add_notifer
+ * @accel_path: valid accelerator path
+ * @notify_data: data argument to the notifier
+ * @notify_func: the notifier function
+ * @accel_group: accelerator group used by the notifier function
+ *
+ * Install a notifier function to be called if an accelerator
+ * map entry changes. @accel_group has to be the accel group
+ * that is being affected (gets an accelerator removed or added,
+ * when the notifier function is executed).
+ */
+void
+gtk_accel_map_add_notifer (const gchar *accel_path,
+ gpointer notify_data,
+ GtkAccelMapNotify notify_func,
+ GtkAccelGroup *accel_group)
+{
+ AccelEntry *entry;
+ AccelHook *ahook;
+ GHook *hook;
+
+ g_return_if_fail (gtk_accel_path_is_valid (accel_path));
+ g_return_if_fail (notify_func != NULL);
+ if (accel_group)
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ entry = accel_path_lookup (accel_path);
+ if (!entry)
+ {
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ entry = accel_path_lookup (accel_path);
+ }
+ if (!entry->hooks)
+ {
+ entry->hooks = g_new (GHookList, 1);
+ g_hook_list_init (entry->hooks, sizeof (AccelHook));
+ entry->hooks->finalize_hook = accel_hook_finalize;
+ }
+ hook = g_hook_alloc (entry->hooks);
+ hook->data = notify_data;
+ hook->func = notify_func;
+ hook->destroy = NULL;
+ ahook = (AccelHook*) hook;
+ ahook->accel_group = accel_group ? g_object_ref (accel_group) : NULL;
+ g_hook_append (entry->hooks, hook);
+}
+
+/**
+ * gtk_accel_map_remove_notifer
+ * @accel_path: valid accelerator path
+ * @notify_data: data argument to the notifier
+ * @notify_func: the notifier function
+ *
+ * Remove a notifier function, previously installed through
+ * gtk_accel_map_add_notifer().
+ */
+void
+gtk_accel_map_remove_notifer (const gchar *accel_path,
+ gpointer notify_data,
+ GtkAccelMapNotify notify_func)
+{
+ AccelEntry *entry;
+
+ g_return_if_fail (gtk_accel_path_is_valid (accel_path));
+ g_return_if_fail (notify_func != NULL);
+
+ entry = accel_path_lookup (accel_path);
+ if (entry && entry->hooks)
+ {
+ GHook *hook = g_hook_find_func_data (entry->hooks, TRUE, notify_func, notify_data);
+
+ if (hook && g_hook_destroy (entry->hooks, hook->hook_id))
+ return; /* successfully removed */
+ }
+ g_warning (G_STRLOC ": no notifier %p(%p) installed for accel path \"%s\"",
+ notify_func, notify_data, accel_path);
+}
+
+/**
+ * gtk_accel_map_lookup_entry
+ * @accel_path: valid accelerator path
+ * @key: accelerator key to be filled in (optional)
+ * @returns: #GQuark for @accel_path or (0) if @accel_path is not known
+ *
+ * Lookup the accelerator entry for @accel_path and fill in @key.
+ * If the lookup revealed no results, (0) is returned, the entry's
+ * #GQuark otherwise.
+ */
+GQuark
+gtk_accel_map_lookup_entry (const gchar *accel_path,
+ GtkAccelKey *key)
+{
+ AccelEntry *entry;
+
+ g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), 0);
+
+ entry = accel_path_lookup (accel_path);
+ if (entry && key)
+ {
+ key->accel_key = entry->accel_key;
+ key->accel_mods = entry->accel_mods;
+ key->accel_flags = 0; // FIXME: global lock?
+ }
+
+ return entry ? g_quark_try_string (entry->accel_path) : 0;
+}
+
+static void
+hash2slist_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **slist_p = user_data;
+
+ *slist_p = g_slist_prepend (*slist_p, value);
+}
+
+static GSList*
+g_hash_table_slist_values (GHashTable *hash_table)
+{
+ GSList *slist = NULL;
+
+ g_return_val_if_fail (hash_table != NULL, NULL);
+
+ g_hash_table_foreach (hash_table, hash2slist_foreach, &slist);
+
+ return slist;
+}
+
+static gboolean
+internal_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace,
+ gboolean simulate)
+{
+ GSList *node, *slist, *win_list, *group_list, *replace_list = NULL;
+ GHashTable *group_hm, *win_hm;
+ gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE, hooks_may_recurse = TRUE;
+ GQuark entry_quark;
+ GHook *hook;
+ AccelEntry *entry = accel_path_lookup (accel_path);
+
+ /* not much todo if there's no entry yet */
+ if (!entry)
+ {
+ if (!simulate)
+ {
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ entry = accel_path_lookup (accel_path);
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+ }
+ return TRUE;
+ }
+
+ /* if there's nothing to change, not much todo either */
+ if (entry->accel_key == accel_key && entry->accel_mods == accel_mods)
+ return FALSE;
+
+ /* nobody's interested, easy going */
+ if (!entry->hooks)
+ {
+ if (!simulate)
+ {
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+ }
+ return TRUE;
+ }
+
+ /* 1) fetch all accel groups affected by this entry */
+ entry_quark = g_quark_try_string (entry->accel_path);
+ group_hm = g_hash_table_new (NULL, NULL);
+ win_hm = g_hash_table_new (NULL, NULL);
+ hook = g_hook_first_valid (entry->hooks, hooks_may_recurse);
+ while (hook)
+ {
+ AccelHook *ahook = (AccelHook*) hook;
+
+ if (ahook->accel_group)
+ g_hash_table_insert (group_hm, ahook->accel_group, ahook->accel_group);
+ hook = g_hook_next_valid (entry->hooks, hook, hooks_may_recurse);
+ }
+
+ /* 2) collect acceleratables affected */
+ group_list = g_hash_table_slist_values (group_hm);
+ for (slist = group_list; slist; slist = slist->next)
+ {
+ GtkAccelGroup *group = slist->data;
+
+ for (node = group->acceleratables; node; node = node->next)
+ g_hash_table_insert (win_hm, node->data, node->data);
+ }
+ g_slist_free (group_list);
+
+ /* 3) include all accel groups used by acceleratables */
+ win_list = g_hash_table_slist_values (win_hm);
+ g_hash_table_destroy (win_hm);
+ for (slist = win_list; slist; slist = slist->next)
+ for (node = gtk_accel_groups_from_acceleratable (slist->data); node; node = node->next)
+ g_hash_table_insert (group_hm, node->data, node->data);
+ group_list = g_hash_table_slist_values (group_hm);
+ g_hash_table_destroy (group_hm);
+
+ /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */
+ for (slist = accel_key ? win_list : NULL; slist; slist = slist->next)
+ if (GTK_IS_WINDOW (slist->data)) /* bad kludge in lack of a GtkAcceleratable */
+ if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods))
+ {
+ seen_accel = TRUE;
+ break;
+ }
+ removable = !seen_accel;
+
+ /* 5) walk all accel groups and search for locks */
+ for (slist = removable ? group_list : NULL; slist; slist = slist->next)
+ {
+ GtkAccelGroup *group = slist->data;
+ GtkAccelGroupEntry *ag_entry;
+ guint i, n;
+
+ n = 0;
+ ag_entry = entry->accel_key ? gtk_accel_group_query (group, entry->accel_key, entry->accel_mods, &n) : NULL;
+ for (i = 0; i < n; i++)
+ if (ag_entry[i].accel_path_quark == entry_quark)
+ {
+ can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+ if (!can_change)
+ goto break_loop_step5;
+ }
+
+ n = 0;
+ ag_entry = accel_key ? gtk_accel_group_query (group, accel_key, accel_mods, &n) : NULL;
+ for (i = 0; i < n; i++)
+ {
+ seen_accel = TRUE;
+ removable = !group->lock_count && !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+ if (!removable)
+ goto break_loop_step5;
+ if (ag_entry[i].accel_path_quark)
+ replace_list = g_slist_prepend (replace_list, GUINT_TO_POINTER (ag_entry->accel_path_quark));
+ }
+ }
+ break_loop_step5:
+
+ /* 6) check whether we can remove existing accelerators */
+ for (slist = removable ? replace_list : NULL; slist; slist = slist->next)
+ if (!internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, TRUE))
+ {
+ removable = FALSE;
+ break;
+ }
+
+ /* 7) check conditions and proceed if possible */
+ change_accel = can_change && (!seen_accel || (removable && replace));
+
+ if (change_accel && !simulate)
+ {
+ guint old_accel_key, old_accel_mods;
+
+ /* 8) remove existing accelerators */
+ for (slist = replace_list; slist; slist = slist->next)
+ internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, FALSE);
+
+ /* 9) install new accelerator */
+ old_accel_key = entry->accel_key;
+ old_accel_mods = entry->accel_mods;
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+ hook = g_hook_first_valid (entry->hooks, hooks_may_recurse);
+ while (hook)
+ {
+ gboolean was_in_call, need_destroy = FALSE;
+ GtkAccelMapNotify hook_func = hook->func;
+ AccelHook *ahook = (AccelHook*) hook;
+
+ was_in_call = G_HOOK_IN_CALL (hook);
+ hook->flags |= G_HOOK_FLAG_IN_CALL;
+ /* need_destroy = */ hook_func (hook->data, g_quark_try_string (entry->accel_path),
+ entry->accel_key, entry->accel_mods,
+ ahook->accel_group,
+ old_accel_key, old_accel_mods);
+ if (!was_in_call)
+ hook->flags &= ~G_HOOK_FLAG_IN_CALL;
+ if (need_destroy)
+ g_hook_destroy_link (entry->hooks, hook);
+ hook = g_hook_next_valid (entry->hooks, hook, hooks_may_recurse);
+ }
+ }
+ g_slist_free (replace_list);
+ g_slist_free (group_list);
+ g_slist_free (win_list);
+
+ return change_accel;
+}
+
+/**
+ * gtk_accel_map_change_entry
+ * @accel_path: valid accelerator path
+ * @accel_key: new accelerator key
+ * @accel_mods: new accelerator modifiers
+ * @replace: %TRUE if other accelerators may be deleted upon conflicts
+ * @returns: %TRUE if the accelerator could be changed, %FALSE otherwise
+ *
+ * Change the @accel_key and @accel_mods currently associated with @accel_path.
+ * Due to conflicts with other accelerators, a change may not alwys be possible,
+ * @replace indicates whether other accelerators may be deleted to resolve such
+ * conflicts. A change will only occour if all conflicts could be resolved (which
+ * might not be the case if conflicting accelerators are locked). Succesfull
+ * changes are indicated by a %TRUE return value.
+ * Changes occouring are also indicated by invocation of notifiers attached to
+ * @accel_path (see gtk_accel_map_add_notifer() on this) and other accelerators
+ * that are being deleted.
+ */
+gboolean
+gtk_accel_map_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace)
+{
+ g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), FALSE);
+
+ return internal_change_entry (accel_path, accel_key, accel_key ? accel_mods : 0, replace, FALSE);
+}
+
+static guint
+accel_map_parse_accel_path (GScanner *scanner)
+{
+ guint accel_key = 0, accel_mods = 0;
+ gchar *path, *accel;
+
+ /* parse accel path */
+ g_scanner_get_next_token (scanner);
+ if (scanner->token != G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ /* test if the next token is an accelerator */
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != G_TOKEN_STRING)
+ {
+ /* if not so, eat that token and error out */
+ g_scanner_get_next_token (scanner);
+ return G_TOKEN_STRING;
+ }
+
+ /* get the full accelerator specification */
+ path = g_strdup (scanner->value.v_string);
+ g_scanner_get_next_token (scanner);
+ accel = g_strdup (scanner->value.v_string);
+
+ /* ensure the entry is present */
+ gtk_accel_map_add_entry (path, 0, 0);
+
+ /* and propagate it */
+ gtk_accelerator_parse (accel, &accel_key, &accel_mods);
+ gtk_accel_map_change_entry (path, accel_key, accel_mods, TRUE);
+
+ g_free (accel);
+ g_free (path);
+
+ /* check correct statement end */
+ g_scanner_get_next_token (scanner);
+ if (scanner->token != ')')
+ return ')';
+ else
+ return G_TOKEN_NONE;
+}
+
+static void
+accel_map_parse_statement (GScanner *scanner)
+{
+ guint expected_token;
+
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token == G_TOKEN_SYMBOL)
+ {
+ guint (*parser_func) (GScanner*);
+
+ parser_func = scanner->value.v_symbol;
+
+ expected_token = parser_func (scanner);
+ }
+ else
+ expected_token = G_TOKEN_SYMBOL;
+
+ /* skip rest of statement on errrors
+ */
+ if (expected_token != G_TOKEN_NONE)
+ {
+ register guint level;
+
+ level = 1;
+ if (scanner->token == ')')
+ level--;
+ if (scanner->token == '(')
+ level++;
+
+ while (!g_scanner_eof (scanner) && level > 0)
+ {
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token == '(')
+ level++;
+ else if (scanner->token == ')')
+ level--;
+ }
+ }
+}
+
+void
+gtk_accel_map_load_scanner (GScanner *scanner)
+{
+ gboolean skip_comment_single;
+ gboolean symbol_2_token;
+ gchar *cpair_comment_single;
+ gpointer saved_symbol;
+
+ g_return_if_fail (scanner != 0);
+
+ /* configure scanner */
+ skip_comment_single = scanner->config->skip_comment_single;
+ scanner->config->skip_comment_single = TRUE;
+ cpair_comment_single = scanner->config->cpair_comment_single;
+ scanner->config->cpair_comment_single = ";\n";
+ symbol_2_token = scanner->config->symbol_2_token;
+ scanner->config->symbol_2_token = FALSE;
+ saved_symbol = g_scanner_lookup_symbol (scanner, "gtk_accel_path");
+ g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", accel_map_parse_accel_path);
+
+ /* outer parsing loop
+ */
+ g_scanner_peek_next_token (scanner);
+ while (scanner->next_token == '(')
+ {
+ g_scanner_get_next_token (scanner);
+
+ accel_map_parse_statement (scanner);
+
+ g_scanner_peek_next_token (scanner);
+ }
+
+ /* restore config */
+ scanner->config->skip_comment_single = skip_comment_single;
+ scanner->config->cpair_comment_single = cpair_comment_single;
+ scanner->config->symbol_2_token = symbol_2_token;
+ g_scanner_scope_remove_symbol (scanner, 0, "gtk_accel_path");
+ if (saved_symbol)
+ g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", saved_symbol);
+}
+
+/**
+ * gtk_accel_map_load_fd
+ * @fd: valid readable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_load().
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_load_fd (gint fd)
+{
+ GScanner *scanner;
+
+ g_return_if_fail (fd >= 0);
+
+ /* create and setup scanner */
+ scanner = g_scanner_new (NULL);
+ g_scanner_input_file (scanner, fd);
+
+ gtk_accel_map_load_scanner (scanner);
+
+ g_scanner_destroy (scanner);
+}
+
+/**
+ * gtk_accel_map_load
+ * @file_name: a file containing accelerator specifications
+ *
+ * Parses a file previously saved with gtk_accel_map_save() for
+ * accelerator specifications, and propagates them accordingly.
+ */
+void
+gtk_accel_map_load (const gchar *file_name)
+{
+ gint fd;
+
+ g_return_if_fail (file_name != NULL);
+
+ if (!g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
+ return;
+
+ fd = open (file_name, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ gtk_accel_map_load_fd (fd);
+
+ close (fd);
+}
+
+static void
+accel_map_print (gpointer data,
+ const gchar *accel_path,
+ guint accel_key,
+ guint accel_mods,
+ gboolean changed)
+{
+ GString *gstring = g_string_new (changed ? NULL : "; ");
+ gint err, fd = GPOINTER_TO_INT (data);
+ gchar *tmp, *name;
+
+ g_string_append (gstring, "(gtk_accel_path \"");
+
+ tmp = g_strescape (accel_path, NULL);
+ g_string_append (gstring, tmp);
+ g_free (tmp);
+
+ g_string_append (gstring, "\" \"");
+
+ name = gtk_accelerator_name (accel_key, accel_mods);
+ tmp = g_strescape (name, NULL);
+ g_free (name);
+ g_string_append (gstring, tmp);
+ g_free (tmp);
+
+ g_string_append (gstring, "\")\n");
+
+ do
+ err = write (fd, gstring->str, gstring->len);
+ while (err < 0 && errno == EINTR);
+
+ g_string_free (gstring, TRUE);
+}
+
+/**
+ * gtk_accel_map_save_fd
+ * @fd: valid writable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_save().
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_save_fd (gint fd)
+{
+ GString *gstring;
+ gint err;
+
+ g_return_if_fail (fd >= 0);
+
+ gstring = g_string_new ("; ");
+ if (g_get_prgname ())
+ g_string_append (gstring, g_get_prgname ());
+ g_string_append (gstring, " GtkAccelMap rc-file -*- scheme -*-\n");
+ g_string_append (gstring, "; this file is an automated accelerator map dump\n");
+ g_string_append (gstring, ";\n");
+
+ do
+ err = write (fd, gstring->str, gstring->len);
+ while (err < 0 && errno == EINTR);
+
+ gtk_accel_map_foreach (GINT_TO_POINTER (fd), accel_map_print);
+}
+
+/**
+ * gtk_accel_map_save
+ * @file_name: the file to contain accelerator specifications
+ *
+ * Saves current accelerator specifications (accelerator path, key
+ * and modifiers) to @file_name.
+ * The file is written in a format suitable to be read back in by
+ * gtk_accel_map_load().
+ */
+void
+gtk_accel_map_save (const gchar *file_name)
+{
+ gint fd;
+
+ g_return_if_fail (file_name != NULL);
+
+ fd = open (file_name, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd < 0)
+ return;
+
+ gtk_accel_map_save_fd (fd);
+
+ close (fd);
+}
+
+/**
+ * gtk_accel_map_foreach
+ * @data: data to be passed into @foreach_func
+ * @foreach_func: function to be executed for each accel map entry
+ *
+ * Loop over the entries in the accelerator map, and execute
+ * @foreach_func on each. The signature of @foreach_func is that of
+ * #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach (gpointer data,
+ GtkAccelMapForeach foreach_func)
+{
+ GSList *entries, *slist, *node;
+
+ g_return_if_fail (foreach_func != NULL);
+
+ entries = g_hash_table_slist_values (accel_entry_ht);
+ for (slist = entries; slist; slist = slist->next)
+ {
+ AccelEntry *entry = slist->data;
+ gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+ for (node = accel_filters; node; node = node->next)
+ if (g_pattern_match_string (node->data, entry->accel_path))
+ goto skip_accel;
+ foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+ skip_accel:
+ }
+ g_slist_free (entries);
+}
+
+void
+gtk_accel_map_foreach_unfiltered (gpointer data,
+ GtkAccelMapForeach foreach_func)
+{
+ GSList *entries, *slist;
+
+ g_return_if_fail (foreach_func != NULL);
+
+ entries = g_hash_table_slist_values (accel_entry_ht);
+ for (slist = entries; slist; slist = slist->next)
+ {
+ AccelEntry *entry = slist->data;
+ gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+ foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+ }
+ g_slist_free (entries);
+}
+
+void
+gtk_accel_map_add_filter (const gchar *filter_pattern)
+{
+ GPatternSpec *pspec;
+ GSList *slist;
+
+ g_return_if_fail (filter_pattern != NULL);
+
+ pspec = g_pattern_spec_new (filter_pattern);
+ for (slist = accel_filters; slist; slist = slist->next)
+ if (g_pattern_spec_equal (pspec, slist->data))
+ {
+ g_pattern_spec_free (pspec);
+ return;
+ }
+ accel_filters = g_slist_prepend (accel_filters, pspec);
+}
diff --git a/gtk/gtkaccelmap.h b/gtk/gtkaccelmap.h
new file mode 100644
index 0000000000..99d0887ff3
--- /dev/null
+++ b/gtk/gtkaccelmap.h
@@ -0,0 +1,81 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GTK_ACCEL_MAP_H__
+#define __GTK_ACCEL_MAP_H__
+
+
+#include <gtk/gtkaccelgroup.h>
+
+G_BEGIN_DECLS
+
+
+/* --- notifier --- */
+typedef void (*GtkAccelMapNotify) (gpointer data,
+ GQuark accel_path_quark,
+ guint accel_key,
+ guint accel_mods,
+ GtkAccelGroup *accel_group,
+ guint old_accel_key,
+ guint old_accel_mods);
+typedef void (*GtkAccelMapForeach) (gpointer data,
+ const gchar *accel_path,
+ guint accel_key,
+ guint accel_mods,
+ gboolean changed);
+
+
+/* --- public API --- */
+GQuark gtk_accel_map_add_entry (const gchar *accel_path,
+ guint accel_key,
+ guint accel_mods);
+void gtk_accel_map_add_notifer (const gchar *accel_path,
+ gpointer notify_data,
+ GtkAccelMapNotify notify_func,
+ GtkAccelGroup *accel_group);
+void gtk_accel_map_remove_notifer (const gchar *accel_path,
+ gpointer notify_data,
+ GtkAccelMapNotify notify_func);
+GQuark gtk_accel_map_lookup_entry (const gchar *accel_path,
+ GtkAccelKey *key);
+gboolean gtk_accel_map_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace);
+void gtk_accel_map_load (const gchar *file_name);
+void gtk_accel_map_save (const gchar *file_name);
+void gtk_accel_map_foreach (gpointer data,
+ GtkAccelMapForeach foreach_func);
+void gtk_accel_map_load_fd (gint fd);
+void gtk_accel_map_load_scanner (GScanner *scanner);
+void gtk_accel_map_save_fd (gint fd);
+
+
+/* --- filter functions --- */
+void gtk_accel_map_add_filter (const gchar *filter_pattern);
+void gtk_accel_map_foreach_unfilterd (gpointer data,
+ GtkAccelMapForeach foreach_func);
+
+
+/* --- internal API --- */
+void _gtk_accel_map_init (void);
+
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_H__ */
diff --git a/gtk/gtkitemfactory.c b/gtk/gtkitemfactory.c
index 6ab691fbad..02fa3df2e6 100644
--- a/gtk/gtkitemfactory.c
+++ b/gtk/gtkitemfactory.c
@@ -39,6 +39,7 @@
#include "gtk/gtkcheckmenuitem.h"
#include "gtk/gtkimagemenuitem.h"
#include "gtk/gtktearoffmenuitem.h"
+#include "gtk/gtkaccelmap.h"
#include "gtk/gtkaccellabel.h"
#include "gdk/gdkkeysyms.h"
#include "gtk/gtkimage.h"
@@ -75,13 +76,6 @@ struct _GtkIFCBData
gpointer func_data;
guint callback_action;
};
-struct _GtkIFDumpData
-{
- GtkPrintFunc print_func;
- gpointer func_data;
- guint modified_only : 1;
- GPatternSpec *pspec;
-};
/* --- prototypes --- */
@@ -114,47 +108,6 @@ static GQuark quark_type_tearoff_item = 0;
static GQuark quark_type_separator_item = 0;
static GQuark quark_type_branch = 0;
static GQuark quark_type_last_branch = 0;
-static GScannerConfig ifactory_scanner_config =
-{
- (
- " \t\n"
- ) /* cset_skip_characters */,
- (
- G_CSET_a_2_z
- "_"
- G_CSET_A_2_Z
- ) /* cset_identifier_first */,
- (
- G_CSET_a_2_z
- "-+_0123456789"
- G_CSET_A_2_Z
- G_CSET_LATINS
- G_CSET_LATINC
- ) /* cset_identifier_nth */,
- ( ";\n" ) /* cpair_comment_single */,
-
- FALSE /* case_sensitive */,
-
- TRUE /* skip_comment_multi */,
- TRUE /* skip_comment_single */,
- FALSE /* scan_comment_multi */,
- TRUE /* scan_identifier */,
- FALSE /* scan_identifier_1char */,
- FALSE /* scan_identifier_NULL */,
- TRUE /* scan_symbols */,
- TRUE /* scan_binary */,
- TRUE /* scan_octal */,
- TRUE /* scan_float */,
- TRUE /* scan_hex */,
- FALSE /* scan_hex_dollar */,
- TRUE /* scan_string_sq */,
- TRUE /* scan_string_dq */,
- TRUE /* numbers_2_int */,
- FALSE /* int_2_float */,
- FALSE /* identifier_2_string */,
- TRUE /* char_2_token */,
- FALSE /* symbol_2_token */,
-};
/* --- functions --- */
@@ -187,22 +140,16 @@ static void
gtk_item_factory_class_init (GtkItemFactoryClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- GtkObjectClass *object_class;
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
gtk_item_factory_class = class;
-
- parent_class = gtk_type_class (GTK_TYPE_OBJECT);
-
- object_class = (GtkObjectClass*) class;
+ parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_item_factory_finalize;
object_class->destroy = gtk_item_factory_destroy;
- class->cpair_comment_single = g_strdup (";\n");
-
class->item_ht = g_hash_table_new (g_str_hash, g_str_equal);
- class->dummy = NULL;
ifactory_item_chunks =
g_mem_chunk_new ("GtkItemFactoryItem",
sizeof (GtkItemFactoryItem),
@@ -285,125 +232,6 @@ gtk_item_factory_callback_marshal (GtkWidget *widget,
}
static void
-gtk_item_factory_propagate_accelerator (GtkItemFactoryItem *item,
- GtkWidget *exclude)
-{
- GSList *widget_list;
- GSList *slist;
-
- if (item->in_propagation)
- return;
-
- item->in_propagation = TRUE;
-
- widget_list = NULL;
- for (slist = item->widgets; slist; slist = slist->next)
- {
- GtkWidget *widget;
-
- widget = slist->data;
-
- if (widget != exclude)
- {
- gtk_widget_ref (widget);
- widget_list = g_slist_prepend (widget_list, widget);
- }
- }
-
- for (slist = widget_list; slist; slist = slist->next)
- {
- GtkWidget *widget;
- GtkAccelGroup *accel_group;
- guint signal_id;
-
- widget = slist->data;
-
- accel_group = gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_accel_group);
-
- signal_id = gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget));
- if (signal_id && accel_group)
- {
- if (item->accelerator_key)
- gtk_widget_add_accelerator (widget,
- "activate",
- accel_group,
- item->accelerator_key,
- item->accelerator_mods,
- GTK_ACCEL_VISIBLE);
- else
- {
- GSList *work;
-
- work = gtk_accel_group_entries_from_object (G_OBJECT (widget));
- while (work)
- {
- GtkAccelEntry *ac_entry;
-
- ac_entry = work->data;
- work = work->next;
- if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
- ac_entry->accel_group == accel_group &&
- ac_entry->signal_id == signal_id)
- gtk_widget_remove_accelerator (GTK_WIDGET (widget),
- ac_entry->accel_group,
- ac_entry->accelerator_key,
- ac_entry->accelerator_mods);
- }
- }
- }
-
- gtk_widget_unref (widget);
- }
-
- g_slist_free (widget_list);
-
- item->in_propagation = FALSE;
-}
-
-static gint
-gtk_item_factory_item_add_accelerator (GtkWidget *widget,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods,
- GtkAccelFlags accel_flags,
- GtkItemFactoryItem *item)
-{
- if (!item->in_propagation &&
- g_slist_find (item->widgets, widget) &&
- accel_signal_id == gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (widget)))
- {
- item->accelerator_key = accel_key;
- item->accelerator_mods = accel_mods;
- item->modified = TRUE;
-
- gtk_item_factory_propagate_accelerator (item, widget);
- }
-
- return TRUE;
-}
-
-static void
-gtk_item_factory_item_remove_accelerator (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods,
- GtkItemFactoryItem *item)
-{
- if (!item->in_propagation &&
- g_slist_find (item->widgets, widget) &&
- item->accelerator_key == accel_key &&
- item->accelerator_mods == accel_mods)
- {
- item->accelerator_key = 0;
- item->accelerator_mods = 0;
- item->modified = TRUE;
-
- gtk_item_factory_propagate_accelerator (item, widget);
- }
-}
-
-static void
gtk_item_factory_item_remove_widget (GtkWidget *widget,
GtkItemFactoryItem *item)
{
@@ -416,8 +244,8 @@ void
gtk_item_factory_add_foreign (GtkWidget *accel_widget,
const gchar *full_path,
GtkAccelGroup *accel_group,
- guint keyval,
- GdkModifierType modifiers)
+ guint accel_key,
+ GdkModifierType accel_mods)
{
GtkItemFactoryClass *class;
GtkItemFactoryItem *item;
@@ -427,7 +255,7 @@ gtk_item_factory_add_foreign (GtkWidget *accel_widget,
class = gtk_type_class (GTK_TYPE_ITEM_FACTORY);
- keyval = keyval != GDK_VoidSymbol ? keyval : 0;
+ accel_key = accel_key != GDK_VoidSymbol ? accel_key : 0;
item = g_hash_table_lookup (class->item_ht, full_path);
if (!item)
@@ -435,11 +263,6 @@ gtk_item_factory_add_foreign (GtkWidget *accel_widget,
item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
item->path = g_strdup (full_path);
- item->accelerator_key = keyval;
- item->accelerator_mods = modifiers;
- item->modified = FALSE;
- item->in_propagation = FALSE;
- item->dummy = NULL;
item->widgets = NULL;
g_hash_table_insert (class->item_ht, item->path, item);
@@ -470,29 +293,12 @@ gtk_item_factory_add_foreign (GtkWidget *accel_widget,
*/
if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (accel_widget)))
{
- if (item->accelerator_key && accel_group)
- gtk_widget_add_accelerator (accel_widget,
- "activate",
- accel_group,
- item->accelerator_key,
- item->accelerator_mods,
- GTK_ACCEL_VISIBLE);
- else
- gtk_widget_remove_accelerators (accel_widget,
- "activate",
- TRUE);
+ if (accel_key && accel_group)
+ {
+ gtk_accel_map_add_entry (full_path, accel_key, accel_mods);
+ _gtk_widget_set_accel_path (accel_widget, full_path, accel_group);
+ }
}
-
- /* keep track of accelerator changes
- */
- gtk_signal_connect_after (GTK_OBJECT (accel_widget),
- "add-accelerator",
- GTK_SIGNAL_FUNC (gtk_item_factory_item_add_accelerator),
- item);
- gtk_signal_connect_after (GTK_OBJECT (accel_widget),
- "remove-accelerator",
- GTK_SIGNAL_FUNC (gtk_item_factory_item_remove_accelerator),
- item);
}
static void
@@ -725,136 +531,6 @@ gtk_item_factory_path_from_widget (GtkWidget *widget)
return gtk_object_get_data_by_id (GTK_OBJECT (widget), quark_item_path);
}
-static gchar *
-item_factory_escape_path (const gchar *path)
-{
- GString *str = g_string_new (NULL);
-
- while (*path)
- {
- gchar c = *path;
-
- switch (c)
- {
- case '\n':
- g_string_append (str, "\\n");
- break;
- case '\r':
- g_string_append (str, "\\r");
- break;
- case '"':
- case '\\':
- g_string_append_c (str, '\\');
- /* Fall through */
- default:
- g_string_append_c (str, c);
- }
-
- path++;
- }
-
- return g_string_free (str, FALSE);
-}
-
-static void
-gtk_item_factory_foreach (gpointer hash_key,
- gpointer value,
- gpointer user_data)
-{
- GtkItemFactoryItem *item;
- GtkIFDumpData *data;
- gchar *string;
- gchar *path;
- gchar *name;
- gchar comment_prefix[2] = "\000\000";
-
- item = value;
- data = user_data;
-
- if (data->pspec && !g_pattern_match_string (data->pspec, item->path))
- return;
-
- comment_prefix[0] = gtk_item_factory_class->cpair_comment_single[0];
-
- path = item_factory_escape_path (hash_key);
- name = gtk_accelerator_name (item->accelerator_key, item->accelerator_mods);
- string = g_strconcat (item->modified ? "" : comment_prefix,
- "(menu-path \"",
- path,
- "\" \"",
- name,
- "\")",
- NULL);
- g_free (path);
- g_free (name);
-
- data->print_func (data->func_data, string);
-
- g_free (string);
-}
-
-void
-gtk_item_factory_dump_items (GPatternSpec *path_pspec,
- gboolean modified_only,
- GtkPrintFunc print_func,
- gpointer func_data)
-{
- GtkIFDumpData data;
-
- g_return_if_fail (print_func != NULL);
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- data.print_func = print_func;
- data.func_data = func_data;
- data.modified_only = (modified_only != FALSE);
- data.pspec = path_pspec;
-
- g_hash_table_foreach (gtk_item_factory_class->item_ht, gtk_item_factory_foreach, &data);
-}
-
-void
-gtk_item_factory_print_func (gpointer FILE_pointer,
- const gchar *string)
-{
- FILE *f_out = FILE_pointer;
-
- g_return_if_fail (FILE_pointer != NULL);
- g_return_if_fail (string != NULL);
-
- fputs (string, f_out);
- fputc ('\n', f_out);
-}
-
-void
-gtk_item_factory_dump_rc (const gchar *file_name,
- GPatternSpec *path_pspec,
- gboolean modified_only)
-{
- FILE *f_out;
-
- g_return_if_fail (file_name != NULL);
-
- f_out = fopen (file_name, "w");
- if (!f_out)
- return;
-
- fputs ("; ", f_out);
- if (g_get_prgname ())
- fputs (g_get_prgname (), f_out);
- fputs (" GtkItemFactory rc-file -*- scheme -*-\n", f_out);
- fputs ("; this file is an automated menu-path dump\n", f_out);
- fputs (";\n", f_out);
-
- gtk_item_factory_dump_items (path_pspec,
- modified_only,
- gtk_item_factory_print_func,
- f_out);
-
- fclose (f_out);
-}
-
void
gtk_item_factory_create_items (GtkItemFactory *ifactory,
guint n_entries,
@@ -1193,25 +869,32 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
parent = gtk_item_factory_get_widget (ifactory, parent_path);
g_return_if_fail (parent != NULL);
}
- g_free (parent_path);
if (GTK_IS_OPTION_MENU (parent))
{
option_menu = GTK_OPTION_MENU (parent);
if (!option_menu->menu)
- gtk_option_menu_set_menu (option_menu, gtk_widget_new (GTK_TYPE_MENU, NULL));
+ {
+ GtkWidget *menu = g_object_new (GTK_TYPE_MENU, NULL);
+ gchar *p = g_strconcat (ifactory->path, parent_path, NULL);
+
+ gtk_menu_set_accel_path (GTK_MENU (menu), p);
+ g_free (p);
+ gtk_option_menu_set_menu (option_menu, menu);
+ }
parent = option_menu->menu;
}
+ g_free (parent_path);
g_return_if_fail (GTK_IS_CONTAINER (parent));
accelerator = entry->accelerator;
widget = gtk_widget_new (type,
- "GtkWidget::visible", TRUE,
- "GtkWidget::sensitive", (type_id != quark_type_separator_item &&
- type_id != quark_type_title),
- "GtkWidget::parent", parent,
+ "visible", TRUE,
+ "sensitive", (type_id != quark_type_separator_item &&
+ type_id != quark_type_title),
+ "parent", parent,
NULL);
if (option_menu && !option_menu->menu_item)
gtk_option_menu_set_history (option_menu, 0);
@@ -1223,32 +906,26 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
if (type_id == quark_type_image_item)
{
GdkPixbuf *pixbuf = NULL;
- image = NULL;
+ image = NULL;
pixbuf = gdk_pixbuf_new_from_inline (-1,
entry->extra_data,
FALSE,
NULL);
-
if (pixbuf)
image = gtk_image_new_from_pixbuf (pixbuf);
-
if (image)
{
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-
gtk_widget_show (image);
}
-
if (pixbuf)
g_object_unref (G_OBJECT (pixbuf));
}
if (type_id == quark_type_stock_item)
{
image = gtk_image_new_from_stock (entry->extra_data, GTK_ICON_SIZE_MENU);
-
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (widget), image);
-
gtk_widget_show (image);
if (gtk_stock_lookup (entry->extra_data, &stock_item))
@@ -1257,8 +934,6 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
accelerator = gtk_accelerator_name (stock_item.keyval, stock_item.modifier);
}
}
-
-
/* install underline accelerators for this item
*/
@@ -1269,12 +944,11 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
GtkWidget *label;
label = gtk_widget_new (GTK_TYPE_ACCEL_LABEL,
- "GtkWidget::visible", TRUE,
- "GtkWidget::parent", widget,
- "GtkAccelLabel::accel_object", widget,
- "GtkMisc::xalign", 0.0,
+ "visible", TRUE,
+ "parent", widget,
+ "accel_widget", widget,
+ "xalign", 0.0,
NULL);
-
gtk_label_set_text_with_mnemonic (GTK_LABEL (label), name);
}
@@ -1283,16 +957,19 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
if (type_id == quark_type_branch ||
type_id == quark_type_last_branch)
{
+ gchar *p;
+
if (entry->callback)
g_warning ("gtk_item_factory_create_item(): Can't specify a callback on a branch: \"%s\"",
entry->path);
-
if (type_id == quark_type_last_branch)
gtk_menu_item_set_right_justified (GTK_MENU_ITEM (widget), TRUE);
parent = widget;
- widget = gtk_widget_new (GTK_TYPE_MENU,
- NULL);
+ widget = gtk_widget_new (GTK_TYPE_MENU, NULL);
+ p = g_strconcat (ifactory->path, path, NULL);
+ gtk_menu_set_accel_path (GTK_MENU (widget), p);
+ g_free (p);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), widget);
}
@@ -1306,10 +983,8 @@ gtk_item_factory_create_item (GtkItemFactory *ifactory,
callback_type,
item_type_path,
widget);
-
if (accelerator != entry->accelerator)
g_free (accelerator);
-
g_free (path);
}
@@ -1595,192 +1270,6 @@ gtk_item_factory_popup_with_data (GtkItemFactory *ifactory,
mouse_button, time);
}
-static guint
-gtk_item_factory_parse_menu_path (GScanner *scanner,
- GtkItemFactoryClass *class)
-{
- GtkItemFactoryItem *item;
-
- g_scanner_get_next_token (scanner);
- if (scanner->token != G_TOKEN_STRING)
- return G_TOKEN_STRING;
-
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token != G_TOKEN_STRING)
- {
- g_scanner_get_next_token (scanner);
- return G_TOKEN_STRING;
- }
-
- item = g_hash_table_lookup (class->item_ht, scanner->value.v_string);
- if (!item)
- {
- item = g_chunk_new (GtkItemFactoryItem, ifactory_item_chunks);
-
- item->path = g_strdup (scanner->value.v_string);
- item->accelerator_key = 0;
- item->accelerator_mods = 0;
- item->modified = TRUE;
- item->in_propagation = FALSE;
- item->dummy = NULL;
- item->widgets = NULL;
-
- g_hash_table_insert (class->item_ht, item->path, item);
- }
- g_scanner_get_next_token (scanner);
-
- if (!item->in_propagation)
- {
- guint old_keyval;
- guint old_mods;
-
- old_keyval = item->accelerator_key;
- old_mods = item->accelerator_mods;
- gtk_accelerator_parse (scanner->value.v_string,
- &item->accelerator_key,
- &item->accelerator_mods);
- if (old_keyval != item->accelerator_key ||
- old_mods != item->accelerator_mods)
- {
- item->modified = TRUE;
- gtk_item_factory_propagate_accelerator (item, NULL);
- }
- }
-
- g_scanner_get_next_token (scanner);
- if (scanner->token != ')')
- return ')';
- else
- return G_TOKEN_NONE;
-}
-
-static void
-gtk_item_factory_parse_statement (GScanner *scanner,
- GtkItemFactoryClass *class)
-{
- guint expected_token;
-
- g_scanner_get_next_token (scanner);
-
- if (scanner->token == G_TOKEN_SYMBOL)
- {
- guint (*parser_func) (GScanner*, GtkItemFactoryClass*);
-
- parser_func = scanner->value.v_symbol;
-
- /* check whether this is a GtkItemFactory symbol.
- */
- if (parser_func == gtk_item_factory_parse_menu_path)
- expected_token = parser_func (scanner, class);
- else
- expected_token = G_TOKEN_SYMBOL;
- }
- else
- expected_token = G_TOKEN_SYMBOL;
-
- /* skip rest of statement on errrors
- */
- if (expected_token != G_TOKEN_NONE)
- {
- register guint level;
-
- level = 1;
- if (scanner->token == ')')
- level--;
- if (scanner->token == '(')
- level++;
-
- while (!g_scanner_eof (scanner) && level > 0)
- {
- g_scanner_get_next_token (scanner);
-
- if (scanner->token == '(')
- level++;
- else if (scanner->token == ')')
- level--;
- }
- }
-}
-
-void
-gtk_item_factory_parse_rc_string (const gchar *rc_string)
-{
- GScanner *scanner;
-
- g_return_if_fail (rc_string != NULL);
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
- scanner = g_scanner_new (&ifactory_scanner_config);
-
- g_scanner_input_text (scanner, rc_string, strlen (rc_string));
-
- gtk_item_factory_parse_rc_scanner (scanner);
-
- g_scanner_destroy (scanner);
-}
-
-void
-gtk_item_factory_parse_rc_scanner (GScanner *scanner)
-{
- gpointer saved_symbol;
-
- g_return_if_fail (scanner != NULL);
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- saved_symbol = g_scanner_lookup_symbol (scanner, "menu-path");
- g_scanner_scope_remove_symbol (scanner, 0, "menu-path");
- g_scanner_scope_add_symbol (scanner, 0, "menu-path", gtk_item_factory_parse_menu_path);
-
- g_scanner_peek_next_token (scanner);
-
- while (scanner->next_token == '(')
- {
- g_scanner_get_next_token (scanner);
-
- gtk_item_factory_parse_statement (scanner, gtk_item_factory_class);
-
- g_scanner_peek_next_token (scanner);
- }
-
- g_scanner_scope_remove_symbol (scanner, 0, "menu-path");
- g_scanner_scope_add_symbol (scanner, 0, "menu-path", saved_symbol);
-}
-
-void
-gtk_item_factory_parse_rc (const gchar *file_name)
-{
- gint fd;
- GScanner *scanner;
-
- g_return_if_fail (file_name != NULL);
-
- if (!g_file_test (file_name, G_FILE_TEST_IS_REGULAR))
- return;
-
- fd = open (file_name, O_RDONLY);
- if (fd < 0)
- return;
-
- if (!gtk_item_factory_class)
- gtk_type_class (GTK_TYPE_ITEM_FACTORY);
-
- ifactory_scanner_config.cpair_comment_single = gtk_item_factory_class->cpair_comment_single;
- scanner = g_scanner_new (&ifactory_scanner_config);
-
- g_scanner_input_file (scanner, fd);
-
- gtk_item_factory_parse_rc_scanner (scanner);
-
- g_scanner_destroy (scanner);
-
- close (fd);
-}
-
void
gtk_item_factory_set_translate_func (GtkItemFactory *ifactory,
GtkTranslateFunc func,
diff --git a/gtk/gtkitemfactory.h b/gtk/gtkitemfactory.h
index 2fba37fd58..394ed0fe26 100644
--- a/gtk/gtkitemfactory.h
+++ b/gtk/gtkitemfactory.h
@@ -79,11 +79,7 @@ struct _GtkItemFactoryClass
{
GtkObjectClass object_class;
- gchar *cpair_comment_single;
-
GHashTable *item_ht;
-
- gpointer dummy;
};
struct _GtkItemFactoryEntry
@@ -122,12 +118,6 @@ struct _GtkItemFactoryEntry
struct _GtkItemFactoryItem
{
gchar *path;
- guint accelerator_key;
- guint accelerator_mods;
- guint modified : 1;
- guint in_propagation : 1;
- gchar *dummy;
-
GSList *widgets;
};
@@ -147,9 +137,6 @@ void gtk_item_factory_construct (GtkItemFactory *ifactory,
/* These functions operate on GtkItemFactoryClass basis.
*/
-void gtk_item_factory_parse_rc (const gchar *file_name);
-void gtk_item_factory_parse_rc_string (const gchar *rc_string);
-void gtk_item_factory_parse_rc_scanner (GScanner *scanner);
void gtk_item_factory_add_foreign (GtkWidget *accel_widget,
const gchar *full_path,
GtkAccelGroup *accel_group,
@@ -168,19 +155,6 @@ GtkWidget* gtk_item_factory_get_widget_by_action (GtkItemFactory *ifactory,
GtkWidget* gtk_item_factory_get_item_by_action (GtkItemFactory *ifactory,
guint action);
-/* If `path_pspec' is passed as `NULL', this function will iterate over
- * all hash entries. otherwise only those entries will be dumped for which
- * the pattern matches, e.g. "<Image>*...".
- */
-void gtk_item_factory_dump_items (GPatternSpec *path_pspec,
- gboolean modified_only,
- GtkPrintFunc print_func,
- gpointer func_data);
-void gtk_item_factory_dump_rc (const gchar *file_name,
- GPatternSpec *path_pspec,
- gboolean modified_only);
-void gtk_item_factory_print_func (gpointer FILE_pointer,
- const gchar *string);
void gtk_item_factory_create_item (GtkItemFactory *ifactory,
GtkItemFactoryEntry *entry,
gpointer callback_data,
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 6e6c9452cc..1279df02d9 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -47,6 +47,7 @@
#include <pango/pango-utils.h> /* For pango_split_file_list */
+#include "gtkaccelmap.h"
#include "gtkdnd.h"
#include "gtkversion.h"
#include "gtkmain.h"
@@ -625,9 +626,9 @@ gtk_init_check (int *argc,
gtk_colormap = gdk_colormap_get_system ();
gtk_type_init (0);
+ _gtk_accel_map_init ();
_gtk_rc_init ();
-
/* Register an exit function to make sure we are able to cleanup.
*/
g_atexit (gtk_exit_func);
diff --git a/gtk/gtkmarshal.list b/gtk/gtkmarshal.list
index e491732558..0cd270728c 100644
--- a/gtk/gtkmarshal.list
+++ b/gtk/gtkmarshal.list
@@ -24,6 +24,7 @@
BOOLEAN:BOXED
BOOLEAN:BOXED,BOXED
BOOLEAN:ENUM
+BOOLEAN:OBJECT,UINT,UINT
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:OBJECT,BOXED,BOXED
@@ -78,7 +79,9 @@ VOID:POINTER,UINT
VOID:STRING
VOID:STRING,STRING
VOID:STRING,INT,POINTER
+VOID:UINT,UINT
+VOID:UINT,UINT,BOXED
+VOID:UINT,STRING
VOID:UINT,BOXED,UINT,FLAGS,FLAGS
VOID:UINT,OBJECT,UINT,FLAGS,FLAGS
-VOID:UINT,STRING
VOID:VOID
diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list
index e491732558..0cd270728c 100644
--- a/gtk/gtkmarshalers.list
+++ b/gtk/gtkmarshalers.list
@@ -24,6 +24,7 @@
BOOLEAN:BOXED
BOOLEAN:BOXED,BOXED
BOOLEAN:ENUM
+BOOLEAN:OBJECT,UINT,UINT
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
BOOLEAN:OBJECT,BOXED,BOXED
@@ -78,7 +79,9 @@ VOID:POINTER,UINT
VOID:STRING
VOID:STRING,STRING
VOID:STRING,INT,POINTER
+VOID:UINT,UINT
+VOID:UINT,UINT,BOXED
+VOID:UINT,STRING
VOID:UINT,BOXED,UINT,FLAGS,FLAGS
VOID:UINT,OBJECT,UINT,FLAGS,FLAGS
-VOID:UINT,STRING
VOID:VOID
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 34781391ce..375b348c40 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -27,6 +27,7 @@
#include <ctype.h>
#include <string.h> /* memset */
#include "gdk/gdkkeysyms.h"
+#include "gtkaccelmap.h"
#include "gtkbindings.h"
#include "gtklabel.h"
#include "gtkmain.h"
@@ -76,6 +77,7 @@ static void gtk_menu_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
static void gtk_menu_destroy (GtkObject *object);
+static void gtk_menu_finalize (GObject *object);
static void gtk_menu_realize (GtkWidget *widget);
static void gtk_menu_unrealize (GtkWidget *widget);
static void gtk_menu_size_request (GtkWidget *widget,
@@ -83,6 +85,7 @@ static void gtk_menu_size_request (GtkWidget *widget,
static void gtk_menu_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_menu_paint (GtkWidget *widget);
+static void gtk_menu_show (GtkWidget *widget);
static gboolean gtk_menu_expose (GtkWidget *widget,
GdkEventExpose *event);
static gboolean gtk_menu_key_press (GtkWidget *widget,
@@ -161,21 +164,16 @@ gtk_menu_get_type (void)
static void
gtk_menu_class_init (GtkMenuClass *class)
{
- GObjectClass *gobject_class;
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
- GtkMenuShellClass *menu_shell_class;
-
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GtkMenuShellClass *menu_shell_class = GTK_MENU_SHELL_CLASS (class);
GtkBindingSet *binding_set;
- gobject_class = (GObjectClass*) class;
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
- container_class = (GtkContainerClass*) class;
- menu_shell_class = (GtkMenuShellClass*) class;
- parent_class = gtk_type_class (gtk_menu_shell_get_type ());
+ parent_class = g_type_class_peek_parent (class);
+ gobject_class->finalize = gtk_menu_finalize;
gobject_class->set_property = gtk_menu_set_property;
gobject_class->get_property = gtk_menu_get_property;
@@ -192,6 +190,7 @@ gtk_menu_class_init (GtkMenuClass *class)
widget_class->unrealize = gtk_menu_unrealize;
widget_class->size_request = gtk_menu_size_request;
widget_class->size_allocate = gtk_menu_size_allocate;
+ widget_class->show = gtk_menu_show;
widget_class->expose_event = gtk_menu_expose;
widget_class->key_press_event = gtk_menu_key_press;
widget_class->motion_notify_event = gtk_menu_motion_notify;
@@ -388,8 +387,6 @@ gtk_menu_destroy (GtkObject *object)
gtk_menu_stop_navigating_submenu (menu);
- gtk_menu_set_accel_group (menu, NULL);
-
if (menu->old_active_menu_item)
{
gtk_widget_unref (menu->old_active_menu_item);
@@ -403,6 +400,12 @@ gtk_menu_destroy (GtkObject *object)
gtk_object_ref (object);
}
+ if (menu->accel_group)
+ {
+ g_object_unref (menu->accel_group);
+ menu->accel_group = NULL;
+ }
+
if (menu->toplevel)
gtk_widget_destroy (menu->toplevel);
if (menu->tearoff_window)
@@ -411,6 +414,15 @@ gtk_menu_destroy (GtkObject *object)
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
+static void
+gtk_menu_finalize (GObject *object)
+{
+ GtkMenu *menu = GTK_MENU (object);
+
+ g_free (menu->accel_path);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
void
gtk_menu_attach_to_widget (GtkMenu *menu,
@@ -828,6 +840,7 @@ gtk_menu_set_accel_group (GtkMenu *menu,
menu->accel_group = accel_group;
if (menu->accel_group)
gtk_accel_group_ref (menu->accel_group);
+ _gtk_menu_refresh_accel_paths (menu, TRUE);
}
}
@@ -839,6 +852,76 @@ gtk_menu_get_accel_group (GtkMenu *menu)
return menu->accel_group;
}
+/**
+ * gtk_menu_set_accel_path
+ * @menu: a valid #GtkMenu
+ * @accel_path: a valid accelerator path
+ *
+ * Sets an accelerator path for this menu from which accelerator paths
+ * for its immediate children, its menu items, can be constructed.
+ * The main purpose of this function is to spare the programmer the
+ * inconvenience of having to call gtk_menu_item_set_accel_path() on
+ * each menu item that should support runtime user changable accelerators.
+ * Instead, by just calling gtk_menu_set_accel_path() on their parent,
+ * each menu item of this menu, that contains a label describing its purpose,
+ * automatically gets an accel path assigned. For example, a menu containing
+ * menu items "New" and "Exit", will, after gtk_menu_set_accel_path (menu,
+ * "<Gnumeric-Sheet>/File"); has been called, assign its items the accel paths:
+ * "<Gnumeric-Sheet>/File/New" and "<Gnumeric-Sheet>/File/Exit".
+ * Assigning accel paths to menu items then enables the user to change
+ * their accelerators at runtime. More details about accelerator paths
+ * and their default setups can be found at gtk_accel_map_add_entry().
+ */
+void
+gtk_menu_set_accel_path (GtkMenu *menu,
+ const gchar *accel_path)
+{
+ g_return_if_fail (GTK_IS_MENU (menu));
+ if (accel_path)
+ g_return_if_fail (accel_path[0] == '<' && strchr (accel_path, '/')); /* simplistic check */
+
+ g_free (menu->accel_path);
+ menu->accel_path = g_strdup (accel_path);
+ if (menu->accel_path)
+ _gtk_menu_refresh_accel_paths (menu, FALSE);
+}
+
+typedef struct {
+ GtkMenu *menu;
+ gboolean group_changed;
+} AccelPropagation;
+
+static void
+refresh_accel_paths_froeach (GtkWidget *widget,
+ gpointer data)
+{
+ AccelPropagation *prop = data;
+
+ if (GTK_IS_MENU_ITEM (widget)) /* should always be true */
+ _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
+ prop->menu->accel_path,
+ prop->menu->accel_group,
+ prop->group_changed);
+}
+
+void
+_gtk_menu_refresh_accel_paths (GtkMenu *menu,
+ gboolean group_changed)
+{
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ if (menu->accel_path && menu->accel_group)
+ {
+ AccelPropagation prop;
+
+ prop.menu = menu;
+ prop.group_changed = group_changed;
+ gtk_container_foreach (GTK_CONTAINER (menu),
+ refresh_accel_paths_froeach,
+ &prop);
+ }
+}
+
void
gtk_menu_reposition (GtkMenu *menu)
{
@@ -1480,20 +1563,33 @@ gtk_menu_expose (GtkWidget *widget,
return FALSE;
}
+static void
+gtk_menu_show (GtkWidget *widget)
+{
+ GtkMenu *menu = GTK_MENU (widget);
+
+ _gtk_menu_refresh_accel_paths (menu, FALSE);
+
+ GTK_WIDGET_CLASS (parent_class)->show (widget);
+}
+
static gboolean
gtk_menu_key_press (GtkWidget *widget,
GdkEventKey *event)
{
GtkMenuShell *menu_shell;
GtkMenu *menu;
+ GtkAccelGroup *accel_group;
gboolean delete = FALSE;
gchar *accel = NULL;
+ guint accel_key, accel_mods;
g_return_val_if_fail (GTK_IS_MENU (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
menu_shell = GTK_MENU_SHELL (widget);
menu = GTK_MENU (widget);
+ accel_group = gtk_menu_get_accel_group (menu);
gtk_menu_stop_navigating_submenu (menu);
@@ -1543,58 +1639,50 @@ gtk_menu_key_press (GtkWidget *widget,
break;
}
+ accel_key = event->keyval;
+ accel_mods = event->state & gtk_accelerator_get_default_mod_mask ();
+
/* Modify the accelerators */
if (menu_shell->active_menu_item &&
- GTK_BIN (menu_shell->active_menu_item)->child &&
- GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL &&
- !gtk_widget_accelerators_locked (menu_shell->active_menu_item) &&
+ GTK_BIN (menu_shell->active_menu_item)->child && /* no seperators */
+ GTK_MENU_ITEM (menu_shell->active_menu_item)->submenu == NULL && /* no submenus */
(delete ||
(gtk_accelerator_valid (event->keyval, event->state) &&
- (event->state ||
- (event->keyval >= GDK_F1 && event->keyval <= GDK_F35)))))
+ (accel_mods ||
+ (accel_key >= GDK_F1 && accel_key <= GDK_F35)))))
{
- GtkMenuItem *menu_item;
- GtkAccelGroup *accel_group;
-
- menu_item = GTK_MENU_ITEM (menu_shell->active_menu_item);
-
- if (!GTK_MENU (widget)->accel_group)
- accel_group = gtk_accel_group_get_default ();
+ GtkWidget *menu_item = menu_shell->active_menu_item;
+ gboolean replace_accels = TRUE;
+ const gchar *path;
+
+ path = _gtk_widget_get_accel_path (menu_item);
+ if (!path)
+ {
+ /* can't change accelerators on menu_items without paths
+ * (basically, those items are accelerator-locked).
+ */
+ /* g_print("item has no path, menu prefix: %s\n", menu->accel_path); */
+ gdk_beep ();
+ }
else
- accel_group = GTK_MENU (widget)->accel_group;
-
- gtk_widget_remove_accelerators (GTK_WIDGET (menu_item),
- gtk_signal_name (menu_item->accelerator_signal),
- TRUE);
-
- if (!delete &&
- 0 == gtk_widget_accelerator_signal (GTK_WIDGET (menu_item),
- accel_group,
- event->keyval,
- event->state))
{
- GSList *slist;
-
- slist = gtk_accel_group_entries_from_object (G_OBJECT (menu_item));
- while (slist)
+ gboolean changed;
+
+ if (delete)
{
- GtkAccelEntry *ac_entry;
-
- ac_entry = slist->data;
-
- if (ac_entry->signal_id == menu_item->accelerator_signal)
- break;
-
- slist = slist->next;
+ accel_key = 0;
+ accel_mods = 0;
+ }
+ changed = gtk_accel_map_change_entry (path, accel_key, accel_mods, replace_accels);
+
+ if (!changed)
+ {
+ /* we failed, probably because this key is in use and
+ * locked already
+ */
+ /* g_print("failed to change\n"); */
+ gdk_beep ();
}
-
- if (!slist)
- gtk_widget_add_accelerator (GTK_WIDGET (menu_item),
- gtk_signal_name (menu_item->accelerator_signal),
- accel_group,
- event->keyval,
- event->state,
- GTK_ACCEL_VISIBLE);
}
}
diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h
index 3948271d1c..225c9a90b2 100644
--- a/gtk/gtkmenu.h
+++ b/gtk/gtkmenu.h
@@ -64,6 +64,7 @@ struct _GtkMenu
GtkWidget *old_active_menu_item;
GtkAccelGroup *accel_group;
+ gchar *accel_path;
GtkMenuPositionFunc position_func;
gpointer position_func_data;
@@ -146,7 +147,10 @@ void gtk_menu_set_active (GtkMenu *menu,
void gtk_menu_set_accel_group (GtkMenu *menu,
GtkAccelGroup *accel_group);
GtkAccelGroup* gtk_menu_get_accel_group (GtkMenu *menu);
-
+void gtk_menu_set_accel_path (GtkMenu *menu,
+ const gchar *accel_path);
+void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
+ gboolean group_changed);
/* A reference count is kept for a widget when it is attached to
* a particular widget. This is typically a menu item; it may also
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index edc7f4f3f4..e269a790f0 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -51,6 +51,7 @@ enum {
static void gtk_menu_item_class_init (GtkMenuItemClass *klass);
static void gtk_menu_item_init (GtkMenuItem *menu_item);
static void gtk_menu_item_destroy (GtkObject *object);
+static void gtk_menu_item_finalize (GObject *object);
static void gtk_menu_item_size_request (GtkWidget *widget,
GtkRequisition *requisition);
static void gtk_menu_item_size_allocate (GtkWidget *widget,
@@ -60,6 +61,7 @@ static void gtk_menu_item_paint (GtkWidget *widget,
static gint gtk_menu_item_expose (GtkWidget *widget,
GdkEventExpose *event);
+
static void gtk_real_menu_item_select (GtkItem *item);
static void gtk_real_menu_item_deselect (GtkItem *item);
static void gtk_real_menu_item_activate_item (GtkMenuItem *item);
@@ -120,18 +122,15 @@ gtk_menu_item_get_type (void)
static void
gtk_menu_item_class_init (GtkMenuItemClass *klass)
{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkContainerClass *container_class;
- GtkItemClass *item_class;
-
- object_class = (GtkObjectClass*) klass;
- widget_class = (GtkWidgetClass*) klass;
- container_class = (GtkContainerClass*) klass;
- item_class = (GtkItemClass*) klass;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
- parent_class = gtk_type_class (gtk_item_get_type ());
+ parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = gtk_menu_item_finalize;
object_class->destroy = gtk_menu_item_destroy;
@@ -141,7 +140,7 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
widget_class->show_all = gtk_menu_item_show_all;
widget_class->hide_all = gtk_menu_item_hide_all;
widget_class->mnemonic_activate = gtk_menu_item_mnemonic_activate;
-
+
container_class->forall = gtk_menu_item_forall;
item_class->select = gtk_real_menu_item_select;
@@ -194,7 +193,6 @@ static void
gtk_menu_item_init (GtkMenuItem *menu_item)
{
menu_item->submenu = NULL;
- menu_item->accelerator_signal = menu_item_signals[ACTIVATE];
menu_item->toggle_size = 0;
menu_item->accelerator_width = 0;
menu_item->show_submenu_indicator = FALSE;
@@ -269,8 +267,17 @@ gtk_menu_item_destroy (GtkObject *object)
if (menu_item->submenu)
gtk_widget_destroy (menu_item->submenu);
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+gtk_menu_item_finalize (GObject *object)
+{
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+
+ g_free (menu_item->accel_path);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
@@ -898,6 +905,107 @@ gtk_menu_item_hide_all (GtkWidget *widget)
}
static void
+gtk_menu_item_accel_name_foreach (GtkWidget *widget,
+ gpointer data)
+{
+ const gchar **path_p = data;
+
+ if (!*path_p)
+ {
+ if (GTK_IS_LABEL (widget))
+ {
+ *path_p = gtk_label_get_text (GTK_LABEL (widget));
+ if (*path_p && (*path_p)[0] == 0)
+ *path_p = NULL;
+ }
+ else if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ gtk_menu_item_accel_name_foreach,
+ data);
+ }
+}
+
+void
+_gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
+ const gchar *prefix,
+ GtkAccelGroup *accel_group,
+ gboolean group_changed)
+{
+ const gchar *path;
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ widget = GTK_WIDGET (menu_item);
+
+ path = _gtk_widget_get_accel_path (widget);
+ if (!path) /* no active accel_path yet */
+ {
+ path = menu_item->accel_path;
+ if (!path && prefix)
+ {
+ gchar *postfix = NULL;
+
+ /* try to construct one from label text */
+ gtk_container_foreach (GTK_CONTAINER (menu_item),
+ gtk_menu_item_accel_name_foreach,
+ &postfix);
+ menu_item->accel_path = postfix ? g_strconcat (prefix, "/", postfix, NULL) : NULL;
+ path = menu_item->accel_path;
+ }
+ if (path)
+ _gtk_widget_set_accel_path (widget, path, accel_group);
+ }
+ else if (group_changed) /* reinstall accelerators */
+ _gtk_widget_set_accel_path (widget, path, accel_group);
+}
+
+/**
+ * gtk_menu_item_set_accel_path
+ * @menu_item: a valid #GtkMenuItem
+ * @accel_path: accelerator path, corresponding to this menu item's funcitonality
+ *
+ * Set the accelerator path on @menu_item, through which runtime changes of the
+ * menu item's accelerator caused by the user can be identified and saved to
+ * persistant storage (see gtk_accel_map_save() on this).
+ * To setup a default accelerator for this menu item, call
+ * gtk_accel_map_add_entry() with the same @accel_path.
+ * See also gtk_accel_map_add_entry() on the specifics of accelerator paths,
+ * and gtk_menu_set_accel_path() for a more convenient variant of this function.
+ */
+void
+gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
+ const gchar *accel_path)
+{
+ GtkWidget *widget;
+
+ g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
+ g_return_if_fail (accel_path && accel_path[0] == '<' && strchr (accel_path, '/'));
+
+ widget = GTK_WIDGET (menu_item);
+
+ /* store new path */
+ g_free (menu_item->accel_path);
+ menu_item->accel_path = g_strdup (accel_path);
+
+ /* forget accelerators associated with old path */
+ _gtk_widget_set_accel_path (widget, NULL, NULL);
+
+ /* install accelerators associated with new path */
+ if (widget->parent)
+ {
+ GtkMenu *menu = GTK_MENU (widget->parent);
+
+ if (menu->accel_group)
+ _gtk_menu_item_refresh_accel_path (GTK_MENU_ITEM (widget),
+ NULL,
+ menu->accel_group,
+ FALSE);
+ }
+}
+
+static void
gtk_menu_item_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
@@ -913,5 +1021,5 @@ gtk_menu_item_forall (GtkContainer *container,
menu_item = GTK_MENU_ITEM (container);
if (bin->child)
- (* callback) (bin->child, callback_data);
+ callback (bin->child, callback_data);
}
diff --git a/gtk/gtkmenuitem.h b/gtk/gtkmenuitem.h
index 1f46eaa8fb..2b53d95e0f 100644
--- a/gtk/gtkmenuitem.h
+++ b/gtk/gtkmenuitem.h
@@ -54,9 +54,9 @@ struct _GtkMenuItem
GtkWidget *submenu;
- guint accelerator_signal;
guint16 toggle_size;
guint16 accelerator_width;
+ gchar *accel_path;
guint show_submenu_indicator : 1;
guint submenu_placement : 1;
@@ -106,6 +106,13 @@ void gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
void gtk_menu_item_set_right_justified (GtkMenuItem *menu_item,
gboolean right_justified);
gboolean gtk_menu_item_get_right_justified (GtkMenuItem *menu_item);
+void gtk_menu_item_set_accel_path (GtkMenuItem *menu_item,
+ const gchar *accel_path);
+
+void _gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item,
+ const gchar *prefix,
+ GtkAccelGroup *accel_group,
+ gboolean group_changed);
#ifndef GTK_DISABLE_DEPRECATED
#define gtk_menu_item_right_justify(menu_item) gtk_menu_item_set_right_justified ((menu_item), TRUE)
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index 4ed8249199..f9b5a08284 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -3540,7 +3540,6 @@ gtk_notebook_menu_item_create (GtkNotebook *notebook,
gtk_widget_show (page->menu_label);
menu_item = gtk_menu_item_new ();
- gtk_widget_lock_accelerators (menu_item);
gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
gtk_notebook_real_page_position (notebook, list));
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index bd666813de..28f7ed8f1b 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -399,8 +399,17 @@ _gtk_settings_parse_convert (GtkRcPropertyParser parser,
if (free_gstring)
g_string_free (gstring, TRUE);
}
- else if (!G_VALUE_HOLDS (src_value, G_TYPE_GSTRING) &&
- g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
+ else if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
+ {
+ if (G_VALUE_HOLDS (dest_value, G_TYPE_STRING))
+ {
+ GString *gstring = g_value_get_boxed (src_value);
+
+ g_value_set_string (dest_value, gstring ? gstring->str : NULL);
+ success = !g_param_value_validate (pspec, dest_value);
+ }
+ }
+ else if (g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
success = g_param_value_convert (pspec, src_value, dest_value, TRUE);
return success;
@@ -420,7 +429,7 @@ apply_queued_setting (GtkSettings *data,
g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
else
{
- gchar *debug = g_strdup_value_contents (&tmp_value);
+ gchar *debug = g_strdup_value_contents (&qvalue->value);
g_message ("%s: failed to retrieve property `%s' of type `%s' from rc file value \"%s\" of type `%s'",
qvalue->origin,
@@ -519,7 +528,7 @@ _gtk_rc_property_parser_from_type (GType type)
void
gtk_settings_install_property (GParamSpec *pspec)
{
- GtkRcPropertyParser parser = NULL;
+ GtkRcPropertyParser parser;
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
@@ -549,9 +558,9 @@ free_value (gpointer data)
}
void
-gtk_settings_set_property_value (GtkSettings *settings,
- const gchar *prop_name,
- const GtkSettingsValue *new_value)
+gtk_settings_set_property_value (GtkSettings *settings,
+ const gchar *prop_name,
+ const GtkSettingsValue *new_value)
{
GtkSettingsValue *qvalue;
GParamSpec *pspec;
@@ -909,7 +918,6 @@ gtk_rc_property_parse_border (const GParamSpec *pspec,
return success;
}
-
void
_gtk_settings_handle_event (GdkEventSetting *event)
{
diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c
index b24741dd8f..10f2328ef3 100644
--- a/gtk/gtksignal.c
+++ b/gtk/gtksignal.c
@@ -43,7 +43,7 @@ gtk_signal_newv (const gchar *name,
g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
- closure = g_signal_type_cclosure_new (object_type, function_offset);
+ closure = function_offset ? g_signal_type_cclosure_new (object_type, function_offset) : 0;
return g_signal_newv (name, object_type, signal_flags, closure, NULL, NULL, marshaller, return_val, n_params, params);
}
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 6ee796b394..646ac49078 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <locale.h>
#include "gtkcontainer.h"
+#include "gtkaccelmap.h"
#include "gtkiconfactory.h"
#include "gtkintl.h"
#include "gtkmain.h"
@@ -69,8 +70,6 @@ enum {
DIRECTION_CHANGED,
GRAB_NOTIFY,
CHILD_NOTIFY,
- ADD_ACCELERATOR,
- REMOVE_ACCELERATOR,
MNEMONIC_ACTIVATE,
GRAB_FOCUS,
FOCUS,
@@ -114,6 +113,7 @@ enum {
WINDOW_STATE_EVENT,
POPUP_MENU,
SHOW_HELP,
+ ACCEL_CLOSURES_CHANGED,
LAST_SIGNAL
};
@@ -230,6 +230,8 @@ static GParamSpecPool *style_property_spec_pool = NULL;
static GQuark quark_property_parser = 0;
static GQuark quark_aux_info = 0;
+static GQuark quark_accel_path = 0;
+static GQuark quark_accel_closures = 0;
static GQuark quark_event_mask = 0;
static GQuark quark_extension_event_mode = 0;
static GQuark quark_parent_window = 0;
@@ -299,6 +301,8 @@ gtk_widget_class_init (GtkWidgetClass *klass)
quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
quark_aux_info = g_quark_from_static_string ("gtk-aux-info");
+ quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
+ quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
quark_event_mask = g_quark_from_static_string ("gtk-event-mask");
quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode");
quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
@@ -341,8 +345,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->direction_changed = gtk_widget_direction_changed;
klass->grab_notify = NULL;
klass->child_notify = NULL;
- klass->add_accelerator = (void*) gtk_accel_group_handle_add;
- klass->remove_accelerator = (void*) gtk_accel_group_handle_remove;
klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
klass->grab_focus = gtk_widget_real_grab_focus;
klass->focus = gtk_widget_real_focus;
@@ -620,12 +622,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
g_cclosure_marshal_VOID__PARAM,
G_TYPE_NONE,
1, G_TYPE_PARAM);
- widget_signals[ADD_ACCELERATOR] =
- gtk_accel_group_create_add (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
- GTK_SIGNAL_OFFSET (GtkWidgetClass, add_accelerator));
- widget_signals[REMOVE_ACCELERATOR] =
- gtk_accel_group_create_remove (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
- GTK_SIGNAL_OFFSET (GtkWidgetClass, remove_accelerator));
widget_signals[MNEMONIC_ACTIVATE] =
g_signal_new ("mnemonic_activate",
GTK_CLASS_TYPE (object_class),
@@ -1020,6 +1016,13 @@ gtk_widget_class_init (GtkWidgetClass *klass)
GTK_SIGNAL_OFFSET (GtkWidgetClass, show_help),
gtk_marshal_NONE__ENUM,
GTK_TYPE_NONE, 1, GTK_TYPE_WIDGET_HELP_TYPE);
+ widget_signals[ACCEL_CLOSURES_CHANGED] =
+ gtk_signal_new ("accel_closures_changed",
+ 0,
+ GTK_CLASS_TYPE (object_class),
+ 0,
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK,
@@ -1035,7 +1038,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
"show_help", 1,
GTK_TYPE_WIDGET_HELP_TYPE,
GTK_WIDGET_HELP_TOOLTIP);
-
gtk_binding_entry_add_signal (binding_set, GDK_F1, GDK_SHIFT_MASK,
"show_help", 1,
GTK_TYPE_WIDGET_HELP_TYPE,
@@ -2497,148 +2499,305 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
}
}
+typedef struct {
+ GClosure closure;
+ guint signal_id;
+} AccelClosure;
+
static void
-gtk_widget_stop_add_accelerator (GtkWidget *widget)
+closure_accel_activate (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
+ AccelClosure *aclosure = (AccelClosure*) closure;
- gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[ADD_ACCELERATOR]);
+ if (GTK_WIDGET_IS_SENSITIVE (closure->data))
+ g_signal_emit (closure->data, aclosure->signal_id, 0);
+
+ /* we handled the accelerator */
+ g_value_set_boolean (return_value, TRUE);
}
static void
-gtk_widget_stop_remove_accelerator (GtkWidget *widget)
+closures_destroy (gpointer data)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
+ GSList *slist, *closures = data;
- gtk_signal_emit_stop (GTK_OBJECT (widget), widget_signals[REMOVE_ACCELERATOR]);
+ for (slist = closures; slist; slist = slist->next)
+ {
+ g_closure_invalidate (slist->data);
+ g_closure_unref (slist->data);
+ }
+ g_slist_free (closures);
}
-void
-gtk_widget_lock_accelerators (GtkWidget *widget)
+static GClosure*
+widget_new_accel_closure (GtkWidget *widget,
+ guint signal_id)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- if (!gtk_widget_accelerators_locked (widget))
+ AccelClosure *aclosure;
+ GClosure *closure = NULL;
+ GSList *slist, *closures;
+
+ closures = g_object_steal_qdata (G_OBJECT (widget), quark_accel_closures);
+ for (slist = closures; slist; slist = slist->next)
+ if (!gtk_accel_group_from_accel_closure (slist->data))
+ {
+ /* reuse this closure */
+ closure = slist->data;
+ break;
+ }
+ if (!closure)
{
- gtk_signal_connect (GTK_OBJECT (widget),
- "add_accelerator",
- GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
- NULL);
- gtk_signal_connect (GTK_OBJECT (widget),
- "remove_accelerator",
- GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
- NULL);
+ closure = g_closure_new_object (sizeof (AccelClosure), G_OBJECT (widget));
+ closures = g_slist_prepend (closures, g_closure_ref (closure));
+ g_closure_sink (closure);
+ g_closure_set_marshal (closure, closure_accel_activate);
}
+ g_object_set_qdata_full (G_OBJECT (widget), quark_accel_closures, closures, closures_destroy);
+
+ aclosure = (AccelClosure*) closure;
+ g_assert (closure->data == widget);
+ g_assert (closure->marshal == closure_accel_activate);
+ aclosure->signal_id = signal_id;
+
+ return closure;
}
+/**
+ * gtk_widget_add_accelerator
+ * @widget: widget to install an accelerator on
+ * @accel_signal: widget signal to emit on accelerator actiavtion
+ * @accel_group: accel group for this widget, added to its toplevel
+ * @accel_key: GDK keyval of the accelerator
+ * @accel_mods: modifier key combination of the accelerator
+ * @accel_flags: flag accelerators, e.g. GTK_ACCEL_VISIBLE
+ *
+ * Install an accelerator for this @widget in @accel_group, that causes
+ * @accel_signal to be emitted if the accelerator is actiavted.
+ * The @accel_group needs to be added to the widget's toplevel via
+ * gtk_window_add_accel_group(), and the signal must be of type %G_RUN_ACTION.
+ * Accelerators added through this function are not user changable during
+ * runtime. If you want to support accelerators that can be changed by the
+ * user, use gtk_accel_map_add_entry() and gtk_menu_item_set_accel_path()
+ * instead.
+ */
void
-gtk_widget_unlock_accelerators (GtkWidget *widget)
+gtk_widget_add_accelerator (GtkWidget *widget,
+ const gchar *accel_signal,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ guint accel_mods,
+ GtkAccelFlags accel_flags)
{
+ GClosure *closure;
+ GSignalQuery query;
+
g_return_if_fail (GTK_IS_WIDGET (widget));
-
- if (gtk_widget_accelerators_locked (widget))
+ g_return_if_fail (accel_signal != NULL);
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
+ if (!query.signal_id ||
+ !(query.signal_flags & G_SIGNAL_ACTION) ||
+ query.return_type != G_TYPE_NONE ||
+ query.n_params)
{
- gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
- GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
- NULL);
- gtk_signal_disconnect_by_func (GTK_OBJECT (widget),
- GTK_SIGNAL_FUNC (gtk_widget_stop_remove_accelerator),
- NULL);
+ /* hmm, should be elaborate enough */
+ g_warning (G_STRLOC ": widget `%s' has no activatable signal \"%s\" without arguments",
+ G_OBJECT_TYPE_NAME (widget), accel_signal);
+ return;
}
+
+ closure = widget_new_accel_closure (widget, query.signal_id);
+
+ /* install the accelerator. since we don't map this onto an accel_path,
+ * the accelerator will automatically be locked.
+ */
+ gtk_accel_group_connect (accel_group,
+ accel_key,
+ accel_mods,
+ accel_flags | GTK_ACCEL_LOCKED,
+ closure,
+ 0);
+
+ g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
}
+/**
+ * gtk_widget_remove_accelerator
+ * @widget: widget to install an accelerator on
+ * @accel_group: accel group for this widget
+ * @accel_key: GDK keyval of the accelerator
+ * @accel_mods: modifier key combination of the accelerator
+ * @returns: whether an accelerator was installed and could be removed
+ *
+ * Remove an accelerator from @widget, previously installed with
+ * gtk_widget_add_accelerator().
+ */
gboolean
-gtk_widget_accelerators_locked (GtkWidget *widget)
+gtk_widget_remove_accelerator (GtkWidget *widget,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ guint accel_mods)
{
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ GtkAccelGroupEntry *ag_entry;
+ GSList *slist;
+ guint n, i;
- return gtk_signal_handler_pending_by_func (GTK_OBJECT (widget),
- widget_signals[ADD_ACCELERATOR],
- TRUE,
- GTK_SIGNAL_FUNC (gtk_widget_stop_add_accelerator),
- NULL) > 0;
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n);
+ for (slist = _gtk_widget_get_accel_closures (widget); slist; slist = slist->next)
+ {
+ /* paranoid sanity checking */
+ for (i = 0; i < n; i++)
+ if (slist->data == (gpointer) ag_entry[i].closure)
+ {
+ gboolean is_removed = gtk_accel_groups_disconnect_closure (slist->data);
+ g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+ return is_removed;
+ }
+ }
+
+ g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)",
+ accel_key, accel_mods, accel_group,
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ return FALSE;
}
-void
-gtk_widget_add_accelerator (GtkWidget *widget,
- const gchar *accel_signal,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods,
- GtkAccelFlags accel_flags)
+GSList*
+_gtk_widget_get_accel_closures (GtkWidget *widget)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (accel_group != NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- gtk_accel_group_add (accel_group,
- accel_key,
- accel_mods,
- accel_flags,
- (GObject*) widget,
- accel_signal);
+ return g_object_get_qdata (G_OBJECT (widget), quark_accel_closures);
}
-void
-gtk_widget_remove_accelerator (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods)
+typedef struct {
+ GtkWidget *widget;
+ GtkAccelGroup *accel_group;
+ const gchar *path;
+ GClosure *closure;
+} AccelPath;
+
+static void
+accel_path_changed (gpointer data,
+ GQuark accel_path_quark,
+ guint accel_key,
+ guint accel_mods,
+ GtkAccelGroup *accel_group,
+ guint old_accel_key,
+ guint old_accel_mods)
+{
+ AccelPath *apath = data;
+ gboolean notify = FALSE;
+
+ if (apath->closure)
+ {
+ /* the closure might have been removed already (due to replacements) */
+ gtk_accel_groups_disconnect_closure (apath->closure);
+ g_closure_unref (apath->closure);
+ apath->closure = NULL;
+ notify = TRUE;
+ }
+ if (accel_key)
+ {
+ apath->closure = widget_new_accel_closure (apath->widget, GTK_WIDGET_GET_CLASS (apath->widget)->activate_signal);
+ g_closure_ref (apath->closure);
+ /* need to specify path to get an unlocked accelerator */
+ gtk_accel_group_connect (apath->accel_group,
+ accel_key,
+ accel_mods,
+ GTK_ACCEL_VISIBLE,
+ apath->closure,
+ accel_path_quark);
+ notify = TRUE;
+ }
+ if (notify)
+ g_signal_emit (apath->widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+}
+
+static void
+destroy_accel_path (gpointer data)
{
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (accel_group != NULL);
+ AccelPath *apath = data;
+
+ /* stop notification */
+ gtk_accel_map_remove_notifer (apath->path, apath, accel_path_changed);
- gtk_accel_group_remove (accel_group,
- accel_key,
- accel_mods,
- (GObject*) widget);
+ /* if the closure is currently connected, get rid of that connection */
+ if (apath->closure)
+ {
+ gtk_accel_groups_disconnect_closure (apath->closure);
+ g_closure_unref (apath->closure);
+ }
+ g_object_unref (apath->accel_group);
+ g_free (apath);
}
+/* accel_group: the accel group used to activate this widget
+ * accel_path: the accel path, associating the accelerator
+ * to activate this widget
+ * set accel path through which this widget can be actiavated.
+ */
void
-gtk_widget_remove_accelerators (GtkWidget *widget,
- const gchar *accel_signal,
- gboolean visible_only)
+_gtk_widget_set_accel_path (GtkWidget *widget,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group)
{
- GSList *slist;
- guint signal_id;
-
+ AccelPath *apath;
+ GtkAccelKey key;
+
g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (accel_signal != NULL);
-
- signal_id = gtk_signal_lookup (accel_signal, GTK_OBJECT_TYPE (widget));
- g_return_if_fail (signal_id != 0);
-
- slist = gtk_accel_group_entries_from_object (G_OBJECT (widget));
- while (slist)
+ g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
+ if (accel_path)
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ if (accel_path)
{
- GtkAccelEntry *ac_entry;
-
- ac_entry = slist->data;
- slist = slist->next;
- if (ac_entry->accel_flags & GTK_ACCEL_VISIBLE &&
- ac_entry->signal_id == signal_id)
- gtk_widget_remove_accelerator (GTK_WIDGET (widget),
- ac_entry->accel_group,
- ac_entry->accelerator_key,
- ac_entry->accelerator_mods);
+ GQuark quark_path = gtk_accel_map_add_entry (accel_path, 0, 0);
+
+ if (!quark_path)
+ return; /* pathologic anyway */
+
+ apath = g_new (AccelPath, 1);
+ apath->widget = widget;
+ apath->accel_group = g_object_ref (accel_group);
+ apath->path = g_quark_to_string (quark_path);
+ apath->closure = NULL;
+ }
+ else
+ apath = NULL;
+
+ /* also removes possible old settings */
+ g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path);
+
+ if (apath)
+ {
+ /* setup accel path hooks to react to changes */
+ gtk_accel_map_add_notifer (apath->path, apath, accel_path_changed, apath->accel_group);
+
+ /* install accelerators for this path */
+ if (gtk_accel_map_lookup_entry (apath->path, &key))
+ accel_path_changed (apath, g_quark_try_string (apath->path), key.accel_key, key.accel_mods, NULL, 0, 0);
}
}
-guint
-gtk_widget_accelerator_signal (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods)
+const gchar*
+_gtk_widget_get_accel_path (GtkWidget *widget)
{
- GtkAccelEntry *ac_entry;
+ AccelPath *apath;
- g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
- g_return_val_if_fail (accel_group != NULL, 0);
-
- ac_entry = gtk_accel_group_get_entry (accel_group, accel_key, accel_mods);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- if (ac_entry && ac_entry->object == (GObject*) widget)
- return ac_entry->signal_id;
- return 0;
+ apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path);
+ return apath ? apath->path : NULL;
}
gboolean
@@ -5361,6 +5520,10 @@ gtk_widget_real_destroy (GtkObject *object)
*/
widget = GTK_WIDGET (object);
+ /* wipe accelerator closures (keep order) */
+ g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
+ g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
+
gtk_grab_remove (widget);
gtk_selection_remove_all (widget);
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 3d9969a249..ee464fa436 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -277,18 +277,6 @@ struct _GtkWidgetClass
void (* child_notify) (GtkWidget *widget,
GParamSpec *pspec);
- /* accelerators */
- void (* add_accelerator) (GtkWidget *widget,
- guint accel_signal_id,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags);
- void (* remove_accelerator) (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods);
-
/* Mnemonics */
gboolean (* mnemonic_activate) (GtkWidget *widget,
gboolean group_cycling);
@@ -496,20 +484,15 @@ void gtk_widget_add_accelerator (GtkWidget *widget,
guint accel_key,
guint accel_mods,
GtkAccelFlags accel_flags);
-void gtk_widget_remove_accelerator (GtkWidget *widget,
- GtkAccelGroup *accel_group,
- guint accel_key,
- guint accel_mods);
-void gtk_widget_remove_accelerators (GtkWidget *widget,
- const gchar *accel_signal,
- gboolean visible_only);
-guint gtk_widget_accelerator_signal (GtkWidget *widget,
+gboolean gtk_widget_remove_accelerator (GtkWidget *widget,
GtkAccelGroup *accel_group,
guint accel_key,
guint accel_mods);
-void gtk_widget_lock_accelerators (GtkWidget *widget);
-void gtk_widget_unlock_accelerators (GtkWidget *widget);
-gboolean gtk_widget_accelerators_locked (GtkWidget *widget);
+void _gtk_widget_set_accel_path (GtkWidget *widget,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group);
+const gchar* _gtk_widget_get_accel_path (GtkWidget *widget);
+GSList* _gtk_widget_get_accel_closures (GtkWidget *widget);
gboolean gtk_widget_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
gboolean gtk_widget_event (GtkWidget *widget,
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 5641caaea7..d5b68cb0f5 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -45,6 +45,7 @@ enum {
ACTIVATE_FOCUS,
ACTIVATE_DEFAULT,
MOVE_FOCUS,
+ ACCELS_CHANGED,
LAST_SIGNAL
};
@@ -220,6 +221,7 @@ static void gtk_window_set_default_size_internal (GtkWindow *window,
static void gtk_window_realize_icon (GtkWindow *window);
static void gtk_window_unrealize_icon (GtkWindow *window);
+static void gtk_window_notify_accels_changed (GtkWindow *window);
static GSList *toplevel_list = NULL;
static GHashTable *mnemonic_hash_table = NULL;
@@ -309,6 +311,8 @@ gtk_window_class_init (GtkWindowClass *klass)
parent_class = gtk_type_class (gtk_bin_get_type ());
+ mnemonic_hash_table = g_hash_table_new (mnemonic_hash, mnemonic_equal);
+
gobject_class->dispose = gtk_window_dispose;
gobject_class->finalize = gtk_window_finalize;
@@ -345,6 +349,7 @@ gtk_window_class_init (GtkWindowClass *klass)
klass->activate_default = gtk_window_real_activate_default;
klass->activate_focus = gtk_window_real_activate_focus;
klass->move_focus = gtk_window_move_focus;
+ klass->accels_changed = NULL;
/* Construct */
g_object_class_install_property (gobject_class,
@@ -493,10 +498,16 @@ gtk_window_class_init (GtkWindowClass *klass)
G_TYPE_NONE,
1,
GTK_TYPE_DIRECTION_TYPE);
-
- if (!mnemonic_hash_table)
- mnemonic_hash_table = g_hash_table_new (mnemonic_hash,
- mnemonic_equal);
+
+ window_signals[ACCELS_CHANGED] =
+ g_signal_new ("accels_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, accels_changed),
+ NULL, NULL,
+ gtk_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
/*
* Key bindings
@@ -1001,6 +1012,38 @@ gtk_window_set_policy (GtkWindow *window,
gtk_widget_queue_resize (GTK_WIDGET (window));
}
+static gboolean
+handle_accels_changed (gpointer data)
+{
+ GtkWindow *window = GTK_WINDOW (data);
+
+ if (window->accels_changed_handler)
+ {
+ gtk_idle_remove (window->accels_changed_handler);
+ window->accels_changed_handler = 0;
+ }
+
+ g_signal_emit (window, window_signals[ACCELS_CHANGED], 0);
+
+ return FALSE;
+}
+
+static void
+gtk_window_notify_accels_changed (GtkWindow *window)
+{
+ if (!window->accels_changed_handler)
+ window->accels_changed_handler = gtk_idle_add (handle_accels_changed, window);
+}
+
+/**
+ * gtk_window_add_accel_group:
+ * @window: window to attach accelerator group to
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Associate @accel_group with @window, such that calling
+ * gtk_accel_groups_activate() on @window will activate accelerators
+ * in @accel_group.
+ **/
void
gtk_window_add_accel_group (GtkWindow *window,
GtkAccelGroup *accel_group)
@@ -1008,9 +1051,19 @@ gtk_window_add_accel_group (GtkWindow *window,
g_return_if_fail (GTK_IS_WINDOW (window));
g_return_if_fail (accel_group != NULL);
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ _gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ g_signal_connect_object (accel_group, "accel_changed",
+ G_CALLBACK (gtk_window_notify_accels_changed),
+ window, G_CONNECT_SWAPPED);
}
+/**
+ * gtk_accel_group_detach:
+ * @accel_group: a #GtkAccelGroup
+ * @object: a #GObject
+ *
+ * Reverses the effects of gtk_window_add_accel_group().
+ **/
void
gtk_window_remove_accel_group (GtkWindow *window,
GtkAccelGroup *accel_group)
@@ -1018,7 +1071,10 @@ gtk_window_remove_accel_group (GtkWindow *window,
g_return_if_fail (GTK_IS_WINDOW (window));
g_return_if_fail (accel_group != NULL);
- gtk_accel_group_detach (accel_group, G_OBJECT (window));
+ g_signal_handlers_disconnect_by_func (accel_group,
+ G_CALLBACK (gtk_window_notify_accels_changed),
+ window);
+ _gtk_accel_group_detach (accel_group, G_OBJECT (window));
}
void
@@ -1048,6 +1104,7 @@ gtk_window_add_mnemonic (GtkWindow *window,
mnemonic->targets = g_slist_prepend (NULL, target);
g_hash_table_insert (mnemonic_hash_table, mnemonic, mnemonic);
}
+ gtk_window_notify_accels_changed (window);
}
void
@@ -1073,6 +1130,7 @@ gtk_window_remove_mnemonic (GtkWindow *window,
g_hash_table_remove (mnemonic_hash_table, mnemonic);
g_free (mnemonic);
}
+ gtk_window_notify_accels_changed (window);
}
gboolean
@@ -1140,6 +1198,7 @@ gtk_window_set_mnemonic_modifier (GtkWindow *window,
g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
window->mnemonic_modifier = modifier;
+ gtk_window_notify_accels_changed (window);
}
/**
@@ -2836,7 +2895,13 @@ gtk_window_finalize (GObject *object)
&window->geometry_info->widget);
g_free (window->geometry_info);
}
-
+
+ if (window->accels_changed_handler)
+ {
+ gtk_idle_remove (window->accels_changed_handler);
+ window->accels_changed_handler = 0;
+ }
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -3371,6 +3436,46 @@ gtk_window_configure_event (GtkWidget *widget,
return TRUE;
}
+/* the accel_key and accel_mods fields of the key have to be setup
+ * upon calling this function. it'll then return whether that key
+ * is at all used as accelerator, and if so will OR in the
+ * accel_flags member of the key.
+ */
+gboolean
+_gtk_window_query_nonaccels (GtkWindow *window,
+ guint accel_key,
+ GdkModifierType accel_mods)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ /* movement keys are considered locked accels */
+ if (!accel_mods)
+ {
+ static const guint bindings[] = {
+ GDK_space, GDK_KP_Space, GDK_Return, GDK_KP_Enter, GDK_Up, GDK_KP_Up, GDK_Down, GDK_KP_Down,
+ GDK_Left, GDK_KP_Left, GDK_Right, GDK_KP_Right, GDK_Tab, GDK_KP_Tab, GDK_ISO_Left_Tab,
+ };
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (bindings); i++)
+ if (bindings[i] == accel_key)
+ return TRUE;
+ }
+
+ /* mnemonics are considered locked accels */
+ if (accel_mods == window->mnemonic_modifier)
+ {
+ GtkWindowMnemonic mkey;
+
+ mkey.window = window;
+ mkey.keyval = accel_key;
+ if (g_hash_table_lookup (mnemonic_hash_table, &mkey))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gint
gtk_window_key_press_event (GtkWidget *widget,
GdkEventKey *event)
@@ -3404,29 +3509,6 @@ gtk_window_key_press_event (GtkWidget *widget,
return handled;
}
-
-static void
-gtk_window_real_activate_default (GtkWindow *window)
-{
- gtk_window_activate_default (window);
-}
-
-static void
-gtk_window_real_activate_focus (GtkWindow *window)
-{
- gtk_window_activate_focus (window);
-}
-
-static void
-gtk_window_move_focus (GtkWindow *window,
- GtkDirectionType dir)
-{
- gtk_widget_child_focus (GTK_WIDGET (window), dir);
-
- if (!GTK_CONTAINER (window)->focus_child)
- gtk_window_set_focus (window, NULL);
-}
-
static gint
gtk_window_key_release_event (GtkWidget *widget,
GdkEventKey *event)
@@ -3452,6 +3534,28 @@ gtk_window_key_release_event (GtkWidget *widget,
return handled;
}
+static void
+gtk_window_real_activate_default (GtkWindow *window)
+{
+ gtk_window_activate_default (window);
+}
+
+static void
+gtk_window_real_activate_focus (GtkWindow *window)
+{
+ gtk_window_activate_focus (window);
+}
+
+static void
+gtk_window_move_focus (GtkWindow *window,
+ GtkDirectionType dir)
+{
+ gtk_widget_child_focus (GTK_WIDGET (window), dir);
+
+ if (!GTK_CONTAINER (window)->focus_child)
+ gtk_window_set_focus (window, NULL);
+}
+
static gint
gtk_window_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event)
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 57a8801810..8e62e60d03 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -104,6 +104,8 @@ struct _GtkWindow
guint frame_top;
guint frame_right;
guint frame_bottom;
+
+ guint accels_changed_handler;
GdkModifierType mnemonic_modifier;
gpointer gtk_reserved1; /* For future GdkScreen * */
@@ -124,6 +126,7 @@ struct _GtkWindowClass
void (* activate_default) (GtkWindow *window);
void (* move_focus) (GtkWindow *window,
GtkDirectionType direction);
+ void (*accels_changed) (GtkWindow *window);
};
#define GTK_TYPE_WINDOW_GROUP (gtk_window_group_get_type ())
@@ -320,6 +323,11 @@ void _gtk_window_constrain_size (GtkWindow *window,
gint *new_height);
GtkWindowGroup *_gtk_window_get_group (GtkWindow *window);
+/* --- internal (GtkAcceleratable) --- */
+gboolean _gtk_window_query_nonaccels (GtkWindow *window,
+ guint accel_key,
+ GdkModifierType accel_mods);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gtk/maketypes.awk b/gtk/maketypes.awk
index 2a88f45495..d0ab8b9f7b 100644
--- a/gtk/maketypes.awk
+++ b/gtk/maketypes.awk
@@ -32,7 +32,11 @@ BEGIN {
printf ("# define GTKTYPEBUILTINS_VAR extern __declspec(dllimport)\n");
printf ("# endif\n");
printf ("#else\n");
- printf ("# define GTKTYPEBUILTINS_VAR extern\n");
+ printf ("# ifdef GTK_COMPILATION\n");
+ printf ("# define GTKTYPEBUILTINS_VAR\n");
+ printf ("# else\n");
+ printf ("# define GTKTYPEBUILTINS_VAR extern\n");
+ printf ("# endif\n");
printf ("#endif\n");
printf ("\n");
}
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 5cbdad12df..dd8134bd4c 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -3047,7 +3047,7 @@ create_menus (void)
NULL);
accel_group = gtk_accel_group_new ();
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ gtk_window_add_accel_group (window, accel_group);
gtk_window_set_title (GTK_WINDOW (window), "menus");
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
@@ -3103,7 +3103,7 @@ create_menus (void)
accel_group,
GDK_F1,
0,
- GTK_ACCEL_VISIBLE | GTK_ACCEL_SIGNAL_VISIBLE);
+ GTK_ACCEL_VISIBLE);
menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
gtk_widget_show (menuitem);
@@ -3128,7 +3128,6 @@ create_menus (void)
GDK_F3,
0,
GTK_ACCEL_VISIBLE);
- gtk_widget_lock_accelerators (menuitem);
optionmenu = gtk_option_menu_new ();
gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
@@ -3287,7 +3286,7 @@ dump_accels (gpointer callback_data,
guint callback_action,
GtkWidget *widget)
{
- gtk_item_factory_dump_items (NULL, FALSE, gtk_item_factory_print_func, stdout);
+ gtk_accel_map_save_fd (1 /* stdout */);
}
static GtkItemFactoryEntry menu_items[] =
@@ -3360,7 +3359,7 @@ create_item_factory (void)
"<main>",
item_factory,
(GtkDestroyNotify) gtk_object_unref);
- gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ gtk_window_add_accel_group (window, accel_group);
gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
diff --git a/tests/testgtkrc b/tests/testgtkrc
index 34bf05497b..4b4cc57416 100644
--- a/tests/testgtkrc
+++ b/tests/testgtkrc
@@ -26,6 +26,9 @@ double-click_timeout = 42
bell-duration = 39
bell_duration = 40
+gtk-cursor-blink-time = 200
+# gtk-menu-bar-accel = F10
+
style "global-style-properties"
{
# xthickness = 20