diff options
-rw-r--r-- | ChangeLog | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 51 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 51 | ||||
-rw-r--r-- | docs/reference/gtk/gtk-sections.txt | 27 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtk-unused.sgml | 39 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkaccelgroup.sgml | 48 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkaccellabel.sgml | 9 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkwidget.sgml | 9 | ||||
-rw-r--r-- | docs/reference/gtk/tmpl/gtkwindow.sgml | 12 | ||||
-rw-r--r-- | gtk/gtkaccelgroup.c | 356 | ||||
-rw-r--r-- | gtk/gtkaccelgroup.h | 35 | ||||
-rw-r--r-- | gtk/gtkaccellabel.c | 22 | ||||
-rw-r--r-- | gtk/gtkaccelmap.c | 321 | ||||
-rw-r--r-- | gtk/gtkaccelmap.h | 24 | ||||
-rw-r--r-- | gtk/gtkitemfactory.c | 2 | ||||
-rw-r--r-- | gtk/gtkmenu.c | 13 | ||||
-rw-r--r-- | gtk/gtkmenu.h | 2 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 122 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 2 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 54 | ||||
-rw-r--r-- | gtk/gtkwindow.h | 4 |
25 files changed, 933 insertions, 525 deletions
@@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 9915522ca4..fb08736ec1 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,54 @@ +Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org> + + * applied patch from owen to get rid of accel map notifiers. + changed things to fix reentrancy and API as discussed on gtk-devel. + + * gtk/gtkaccelgroup.[hc]: + (gtk_accel_group_finalize): unregister this accel group from all + accel map paths. + (accel_closure_invalidate): handle invalidation of closures by + disconnecting their accelerators. + (quick_accel_add): move closure connection and changed notification + into this function to reduce code duplication. don't emit change + notification on closurers without accelerators. + (quick_accel_remove): rewrite, do the exact opposite of quick_accel_add + for a GtkAccelGroupEntry. + (gtk_accel_group_connect): get rid of the accel_path_quark argument. + (gtk_accel_group_connect_by_path): new function to add accelerators + with an accel path. + (gtk_accel_group_disconnect_closure): new function, disconnect a + closure from of an accel group. + (gtk_accel_group_disconnect): loop over all closure for a accel_ley, + accel_mods pair and remove them. + (_gtk_accel_group_reconnect): new function that basically does + gtk_accel_group_disconnect_closure() and + gtk_accel_group_connect_by_path() once an accel path changed. + (gtk_accel_groups_disconnect_closure): remove this, there's + gtk_accel_group_disconnect_closure(). + + * gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now, + nuke notifiers. + (_gtk_accel_path_is_valid): make this non-static for + gtkwidget.c and gtkaccelgroup.c assertions. + (gtk_accel_map_add_notifer): removed this function. + (gtk_accel_map_remove_notifer): same. + (_gtk_accel_map_add_group): + (_gtk_accel_map_remove_group): (un-)register accel groups, with + accel paths for correct propagation. + (gtk_accel_map_add_entry): return void. + (gtk_accel_map_lookup): return gboolean instead of GQuark. + + * gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always + set accel_path on widgets. + + * gtk/gtkwidget.[hc]: + (accel_path_changed): got rid of this, changes are handled by + accel maps internally now. + (_gtk_widget_set_accel_path): get things to work without notifiers. + (gtk_widget_list_accel_closures): list accel closures of a widget. + + * gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed. + 2001-11-20 Matthias Clasen <matthiasc@poet.de> * gtk/gtkcontainer.c (gtk_container_propagate_expose): Typo fix. diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt index fc97655694..40ea35c2f1 100644 --- a/docs/reference/gtk/gtk-sections.txt +++ b/docs/reference/gtk/gtk-sections.txt @@ -8,12 +8,14 @@ GtkAccelGroup gtk_accel_group_get_type gtk_accel_group_new gtk_accel_group_connect +gtk_accel_group_connect_by_path gtk_accel_group_disconnect +gtk_accel_group_disconnect_key gtk_accel_group_query -gtk_accel_group_activate -gtk_accel_groups_activate gtk_accel_group_lock gtk_accel_group_unlock +gtk_accel_group_from_accel_closure +gtk_accel_groups_activate gtk_accelerator_valid gtk_accelerator_parse gtk_accelerator_name @@ -33,18 +35,16 @@ GTK_ACCEL_GROUP_GET_CLASS <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 +gtk_accel_map_load_scanner </SECTION> <SECTION> @@ -52,8 +52,8 @@ gtk_accel_map_save_fd <TITLE>GtkAccelLabel</TITLE> GtkAccelLabel gtk_accel_label_new -gtk_accel_label_get_accel_object -gtk_accel_label_set_accel_object +gtk_accel_label_get_accel_closure +gtk_accel_label_set_accel_closure gtk_accel_label_get_accel_widget gtk_accel_label_set_accel_widget gtk_accel_label_get_accel_width @@ -1290,9 +1290,6 @@ GtkItemFactoryEntry GtkItemFactoryItem gtk_item_factory_new gtk_item_factory_construct -gtk_item_factory_parse_rc -gtk_item_factory_parse_rc_string -gtk_item_factory_parse_rc_scanner gtk_item_factory_add_foreign gtk_item_factory_from_widget gtk_item_factory_path_from_widget @@ -1300,9 +1297,6 @@ gtk_item_factory_get_item gtk_item_factory_get_widget gtk_item_factory_get_widget_by_action gtk_item_factory_get_item_by_action -gtk_item_factory_dump_items -gtk_item_factory_dump_rc -gtk_item_factory_print_func gtk_item_factory_create_item gtk_item_factory_create_items gtk_item_factory_create_items_ac @@ -1674,7 +1668,6 @@ GTK_OBJECT_TYPE GTK_OBJECT_TYPE_NAME GtkObjectFlags GTK_OBJECT_FLAGS -GTK_OBJECT_DESTROYED GTK_OBJECT_FLOATING GTK_OBJECT_CONNECTED GTK_OBJECT_SET_FLAGS @@ -3467,8 +3460,7 @@ gtk_widget_get_child_requisition gtk_widget_size_allocate gtk_widget_add_accelerator gtk_widget_remove_accelerator -gtk_widget_remove_accelerators -gtk_widget_accelerator_signal +gtk_widget_list_accel_closures gtk_widget_event gtk_widget_activate gtk_widget_reparent @@ -3519,7 +3511,6 @@ gtk_widget_shape_combine_mask gtk_widget_path gtk_widget_class_path gtk_widget_get_composite_name -gtk_widget_lock_accelerators gtk_widget_modify_style gtk_widget_get_modifier_style gtk_widget_modify_fg @@ -3541,8 +3532,6 @@ gtk_widget_set_app_paintable gtk_widget_set_double_buffered gtk_widget_set_composite_name gtk_widget_set_scroll_adjustments -gtk_widget_unlock_accelerators -gtk_widget_accelerators_locked gtk_widget_mnemonic_activate gtk_widget_class_install_style_property gtk_widget_class_install_style_property_parser diff --git a/docs/reference/gtk/tmpl/gtk-unused.sgml b/docs/reference/gtk/tmpl/gtk-unused.sgml index 3bb9d320f3..6f3500c43b 100644 --- a/docs/reference/gtk/tmpl/gtk-unused.sgml +++ b/docs/reference/gtk/tmpl/gtk-unused.sgml @@ -514,6 +514,19 @@ This is a private struct used by GTK+ internally, don't worry about it. </para> +<!-- ##### USER_FUNCTION GtkAccelMapNotify ##### --> +<para> + +</para> + +@data: +@accel_path_quark: +@accel_key: +@accel_mods: +@accel_group: +@old_accel_key: +@old_accel_mods: + <!-- ##### ENUM GtkAnchorType ##### --> <para> @@ -1299,6 +1312,13 @@ the #GtkAdjustment which sets the range of the scale. </para> +<!-- ##### SIGNAL GtkWindow::accels-changed ##### --> +<para> + +</para> + +@window: the object which received the signal. + <!-- ##### ARG GtkWindow:auto-shrink ##### --> <para> If the window shrinks automatically when widgets within it shrink. @@ -1484,6 +1504,25 @@ If the window shrinks automatically when widgets within it shrink. @accel_label: @accel_object: +<!-- ##### FUNCTION gtk_accel_map_add_notifer ##### --> +<para> + +</para> + +@accel_path: +@notify_data: +@notify_func: +@accel_group: + +<!-- ##### FUNCTION gtk_accel_map_remove_notifer ##### --> +<para> + +</para> + +@accel_path: +@notify_data: +@notify_func: + <!-- ##### FUNCTION gtk_arg_copy ##### --> <para> It will either copy data into an existing argument or allocate a new argument diff --git a/docs/reference/gtk/tmpl/gtkaccelgroup.sgml b/docs/reference/gtk/tmpl/gtkaccelgroup.sgml index b069f7e738..f397377766 100644 --- a/docs/reference/gtk/tmpl/gtkaccelgroup.sgml +++ b/docs/reference/gtk/tmpl/gtkaccelgroup.sgml @@ -64,23 +64,35 @@ An object representing and maintaining a group of accelerators. @accel_mods: @accel_flags: @closure: -@accel_path_quark: <!-- # Unused Parameters # --> +@accel_path_quark: @path_quark: +<!-- ##### FUNCTION gtk_accel_group_connect_by_path ##### --> +<para> + +</para> + +@accel_group: +@accel_path: +@closure: + + <!-- ##### FUNCTION gtk_accel_group_disconnect ##### --> <para> </para> @accel_group: +@closure: +@Returns: +<!-- # Unused Parameters # --> @accel_key: @accel_mods: -@Returns: -<!-- ##### FUNCTION gtk_accel_group_query ##### --> +<!-- ##### FUNCTION gtk_accel_group_disconnect_key ##### --> <para> </para> @@ -88,21 +100,19 @@ An object representing and maintaining a group of accelerators. @accel_group: @accel_key: @accel_mods: -@n_entries: @Returns: -<!-- ##### FUNCTION gtk_accel_groups_activate ##### --> +<!-- ##### FUNCTION gtk_accel_group_query ##### --> <para> </para> -@acceleratable: +@accel_group: @accel_key: @accel_mods: +@n_entries: @Returns: -<!-- # Unused Parameters # --> -@object: <!-- ##### FUNCTION gtk_accel_group_lock ##### --> @@ -121,6 +131,28 @@ An object representing and maintaining a group of accelerators. @accel_group: +<!-- ##### FUNCTION gtk_accel_group_from_accel_closure ##### --> +<para> + +</para> + +@closure: +@Returns: + + +<!-- ##### FUNCTION gtk_accel_groups_activate ##### --> +<para> + +</para> + +@acceleratable: +@accel_key: +@accel_mods: +@Returns: +<!-- # Unused Parameters # --> +@object: + + <!-- ##### FUNCTION gtk_accelerator_valid ##### --> <para> diff --git a/docs/reference/gtk/tmpl/gtkaccellabel.sgml b/docs/reference/gtk/tmpl/gtkaccellabel.sgml index 4587cf7515..dac75d7438 100644 --- a/docs/reference/gtk/tmpl/gtkaccellabel.sgml +++ b/docs/reference/gtk/tmpl/gtkaccellabel.sgml @@ -94,6 +94,15 @@ Creates a new #GtkAccelLabel. @Returns: a new #GtkAccelLabel. +<!-- ##### FUNCTION gtk_accel_label_set_accel_closure ##### --> +<para> + +</para> + +@accel_label: +@closure: + + <!-- ##### FUNCTION gtk_accel_label_get_accel_widget ##### --> <para> diff --git a/docs/reference/gtk/tmpl/gtkwidget.sgml b/docs/reference/gtk/tmpl/gtkwidget.sgml index 76769b73b5..dbe5a82a33 100644 --- a/docs/reference/gtk/tmpl/gtkwidget.sgml +++ b/docs/reference/gtk/tmpl/gtkwidget.sgml @@ -530,6 +530,15 @@ GtkWidget @Returns: +<!-- ##### FUNCTION gtk_widget_list_accel_closures ##### --> +<para> + +</para> + +@widget: +@Returns: + + <!-- ##### FUNCTION gtk_widget_event ##### --> <para> diff --git a/docs/reference/gtk/tmpl/gtkwindow.sgml b/docs/reference/gtk/tmpl/gtkwindow.sgml index b8111b4362..d5a4f46478 100644 --- a/docs/reference/gtk/tmpl/gtkwindow.sgml +++ b/docs/reference/gtk/tmpl/gtkwindow.sgml @@ -694,35 +694,35 @@ it's larger @height: -<!-- ##### SIGNAL GtkWindow::accels-changed ##### --> +<!-- ##### SIGNAL GtkWindow::activate-default ##### --> <para> </para> @window: the object which received the signal. -<!-- ##### SIGNAL GtkWindow::activate-default ##### --> +<!-- ##### SIGNAL GtkWindow::activate-focus ##### --> <para> </para> @window: the object which received the signal. -<!-- ##### SIGNAL GtkWindow::activate-focus ##### --> +<!-- ##### SIGNAL GtkWindow::frame-event ##### --> <para> </para> @window: the object which received the signal. +@event: +@Returns: -<!-- ##### SIGNAL GtkWindow::frame-event ##### --> +<!-- ##### SIGNAL GtkWindow::keys-changed ##### --> <para> </para> @window: the object which received the signal. -@event: -@Returns: <!-- ##### SIGNAL GtkWindow::move-focus ##### --> <para> diff --git a/gtk/gtkaccelgroup.c b/gtk/gtkaccelgroup.c index 7d5ec04b8f..8106f813e1 100644 --- a/gtk/gtkaccelgroup.c +++ b/gtk/gtkaccelgroup.c @@ -52,7 +52,7 @@ static guint default_accel_mod_mask = (GDK_SHIFT_MASK | /* --- functions --- */ /** - * gtk_accel_map_change_entry + * gtk_accel_group_get_type * @returns: the type ID for accelerator groups */ GType @@ -135,6 +135,19 @@ static void gtk_accel_group_finalize (GObject *object) { GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object); + guint i; + + for (i = 0; i < accel_group->n_accels; i++) + { + GtkAccelGroupEntry *entry = &accel_group->priv_accels[i]; + + if (entry->accel_path_quark) + { + const gchar *accel_path = g_quark_to_string (entry[i].accel_path_quark); + + _gtk_accel_map_remove_group (accel_path, accel_group); + } + } g_free (accel_group->priv_accels); @@ -300,10 +313,12 @@ gtk_accel_group_unlock (GtkAccelGroup *accel_group) } static void -accel_tag_func (gpointer data, - GClosure *closure) +accel_closure_invalidate (gpointer data, + GClosure *closure) { - /* GtkAccelGroup *accel_group = data; */ + GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (data); + + gtk_accel_group_disconnect (accel_group, closure); } static int @@ -330,11 +345,14 @@ quick_accel_add (GtkAccelGroup *accel_group, guint pos, i = accel_group->n_accels++; GtkAccelGroupEntry key; + /* find position */ 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; + + /* insert at position, ref closure */ 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])); @@ -344,9 +362,71 @@ quick_accel_add (GtkAccelGroup *accel_group, accel_group->priv_accels[pos].closure = g_closure_ref (closure); accel_group->priv_accels[pos].accel_path_quark = path_quark; g_closure_sink (closure); + + /* handle closure invalidation and reverse lookups */ + g_closure_add_invalidate_notifier (closure, accel_group, accel_closure_invalidate); + + /* get accel path notification */ + if (path_quark) + _gtk_accel_map_add_group (g_quark_to_string (path_quark), accel_group); + + /* connect and notify changed */ + if (accel_key) + { + gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods); + GQuark accel_quark = g_quark_from_string (accel_name); - /* tag closure for backwards lookup */ - g_closure_add_invalidate_notifier (closure, accel_group, accel_tag_func); + g_free (accel_name); + + /* 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 void +quick_accel_remove (GtkAccelGroup *accel_group, + GtkAccelGroupEntry *entry) +{ + guint pos = entry - accel_group->priv_accels; + GQuark accel_quark = 0; + guint accel_key = entry->key.accel_key; + GdkModifierType accel_mods = entry->key.accel_mods; + GClosure *closure = entry->closure; + + /* quark for notification */ + if (accel_key) + { + gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods); + + accel_quark = g_quark_from_string (accel_name); + g_free (accel_name); + } + + /* clean up closure invalidate notification and disconnect */ + g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate); + if (accel_quark) + g_signal_handlers_disconnect_matched (accel_group, + G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_CLOSURE, + signal_accel_activate, accel_quark, + closure, NULL, NULL); + /* clean up accel path notification */ + if (entry->accel_path_quark) + _gtk_accel_map_remove_group (g_quark_to_string (entry->accel_path_quark), accel_group); + + /* physically remove */ + accel_group->n_accels -= 1; + g_memmove (entry, entry + 1, + (accel_group->n_accels - pos) * sizeof (accel_group->priv_accels[0])); + + /* and notify */ + if (accel_quark) + g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure); + + /* remove quick_accel_add() refcount */ + g_closure_unref (closure); } static GtkAccelGroupEntry* @@ -382,31 +462,6 @@ quick_accel_find (GtkAccelGroup *accel_group, return entry; } -static GSList* -quick_accel_remove (GtkAccelGroup *accel_group, - guint accel_key, - GdkModifierType 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_connect * @accel_group: the ccelerator group to install an accelerator in @@ -414,90 +469,107 @@ quick_accel_remove (GtkAccelGroup *accel_group, * @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 * * 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. + * Note that, due to implementation details, a single closure can only be + * connected to one accelerator group. */ void gtk_accel_group_connect (GtkAccelGroup *accel_group, guint accel_key, GdkModifierType accel_mods, GtkAccelFlags accel_flags, - GClosure *closure, - GQuark accel_path_quark) + GClosure *closure) { - 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); + g_return_if_fail (gtk_accel_group_from_accel_closure (closure) == NULL); - 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); + g_object_ref (accel_group); + if (!closure->is_invalid) + quick_accel_add (accel_group, accel_key, accel_mods, accel_flags, closure, 0); + g_object_unref (accel_group); } -static gboolean -accel_group_disconnect_closure (GtkAccelGroup *accel_group, - guint accel_key, - GdkModifierType accel_mods, - GClosure *closure) +/** + * gtk_accel_group_connect_by_path + * @accel_group: the ccelerator group to install an accelerator in + * @accel_path: path used for determining key and modifiers. + * @closure: closure to be executed upon accelerator activation + * + * Install an accelerator in this group, using a accelerator path to look + * up the appropriate key and modifiers. (See gtk_accel_map_add_entry()) + * 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 the key and modifiers + * for the path. + * The signature used for the @closure is that of #GtkAccelGroupActivate. + */ +void +gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group, + const gchar *accel_path, + GClosure *closure) { - gchar *accel_name; - GQuark accel_quark; - GSList *clist , *slist; - gboolean removed_some = FALSE; + guint accel_key = 0; + GdkModifierType accel_mods = 0; + GtkAccelKey key; - accel_name = gtk_accelerator_name (accel_key, accel_mods); - accel_quark = g_quark_from_string (accel_name); - g_free (accel_name); + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); + g_return_if_fail (closure != NULL); + g_return_if_fail (_gtk_accel_path_is_valid (accel_path)); - clist = quick_accel_remove (accel_group, accel_key, accel_mods); - if (!clist) - return FALSE; + if (closure->is_invalid) + return; g_object_ref (accel_group); - 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); + if (gtk_accel_map_lookup_entry (accel_path, &key)) + { + accel_key = key.accel_key; + accel_mods = key.accel_mods; + } + + quick_accel_add (accel_group, accel_key, accel_mods, GTK_ACCEL_VISIBLE, closure, + g_quark_from_string (accel_path)); g_object_unref (accel_group); - - return removed_some; } /** * gtk_accel_group_disconnect + * @accel_group: the accelerator group to remove an accelerator from + * @closure: the closure to remove from this accelerator group + * @returns: %TRUE if the closure was found and got disconnected + * + * Remove an accelerator previously installed through + * gtk_accel_group_connect(). + */ +gboolean +gtk_accel_group_disconnect (GtkAccelGroup *accel_group, + GClosure *closure) +{ + guint i; + + g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE); + + for (i = 0; i < accel_group->n_accels; i++) + if (accel_group->priv_accels[i].closure == closure) + { + g_object_ref (accel_group); + quick_accel_remove (accel_group, accel_group->priv_accels + i); + g_object_unref (accel_group); + return TRUE; + } + return FALSE; +} + +/** + * gtk_accel_group_disconnect_key * @accel_group: the ccelerator group to install an accelerator in * @accel_key: key value of the accelerator * @accel_mods: modifier combination of the accelerator @@ -507,13 +579,71 @@ accel_group_disconnect_closure (GtkAccelGroup *accel_group, * gtk_accel_group_connect(). */ gboolean -gtk_accel_group_disconnect (GtkAccelGroup *accel_group, - guint accel_key, - GdkModifierType accel_mods) +gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group, + guint accel_key, + GdkModifierType accel_mods) { + GtkAccelGroupEntry *entries; + GSList *slist, *clist = NULL; + gboolean removed_one = FALSE; + guint n; + g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE); - return accel_group_disconnect_closure (accel_group, accel_key, accel_mods, NULL); + g_object_ref (accel_group); + + entries = quick_accel_find (accel_group, accel_key, accel_mods, &n); + while (n--) + { + GClosure *closure = g_closure_ref (entries[n].closure); + + clist = g_slist_prepend (clist, closure); + } + + for (slist = clist; slist; slist = slist->next) + { + GClosure *closure = slist->data; + + removed_one |= gtk_accel_group_disconnect (accel_group, closure); + g_closure_unref (closure); + } + g_slist_free (clist); + + g_object_unref (accel_group); + + return removed_one; +} + +void +_gtk_accel_group_reconnect (GtkAccelGroup *accel_group, + GQuark accel_path_quark) +{ + GSList *slist, *clist = NULL; + guint i; + + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); + + g_object_ref (accel_group); + + for (i = 0; i < accel_group->n_accels; i++) + if (accel_group->priv_accels[i].accel_path_quark == accel_path_quark) + { + GClosure *closure = g_closure_ref (accel_group->priv_accels[i].closure); + + clist = g_slist_prepend (clist, closure); + } + + for (slist = clist; slist; slist = slist->next) + { + GClosure *closure = slist->data; + + gtk_accel_group_disconnect (accel_group, closure); + gtk_accel_group_connect_by_path (accel_group, g_quark_to_string (accel_path_quark), closure); + g_closure_unref (closure); + } + g_slist_free (clist); + + g_object_unref (accel_group); } GtkAccelGroupEntry* @@ -535,38 +665,6 @@ gtk_accel_group_query (GtkAccelGroup *accel_group, return entries; } -static gboolean -find_accel_closure (GtkAccelKey *key, - GClosure *closure, - gpointer data) -{ - return data == (gpointer) closure; -} - -gboolean -gtk_accel_groups_disconnect_closure (GClosure *closure) -{ - GtkAccelGroup *group; - - g_return_val_if_fail (closure != NULL, FALSE); - - group = gtk_accel_group_from_accel_closure (closure); - if (group) - { - 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) - { - accel_group_disconnect_closure (group, key->accel_key, key->accel_mods, closure); - return TRUE; - } - } - return FALSE; -} - GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure *closure) { @@ -574,15 +672,15 @@ gtk_accel_group_from_accel_closure (GClosure *closure) 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 + /* a few remarks on wat we do here. in general, we need a way to reverse 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. + * use the invalidation notifier on the closure itself (which we need to install + * anyway), 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) + if (closure->notifiers[i].notify == accel_closure_invalidate) return closure->notifiers[i].data; return NULL; @@ -791,10 +889,10 @@ is_release (const gchar *string) * @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 - * "<Release>z" (the last one is for key release). + * format looks like "<Control>a" or "<Shift><Alt>F1" or + * "<Release>z" (the last one is for key release). * The parser is fairly liberal and allows lower or upper case, - * and also abbreviations such as "<Ctl>" and "<Ctrl>". + * and also abbreviations such as "<Ctl>" and "<Ctrl>". * * If the parse fails, @accelerator_key and @accelerator_mods will * be set to 0 (zero). @@ -911,7 +1009,7 @@ gtk_accelerator_parse (const gchar *accelerator, * 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". + * this function returns "<Control>q". * * The caller of this function must free the returned string. */ diff --git a/gtk/gtkaccelgroup.h b/gtk/gtkaccelgroup.h index 5fca1a33b3..cfb207f8a7 100644 --- a/gtk/gtkaccelgroup.h +++ b/gtk/gtkaccelgroup.h @@ -88,20 +88,23 @@ struct _GtkAccelKey /* -- Accelerator Groups --- */ -GType gtk_accel_group_get_type (void); -GtkAccelGroup* gtk_accel_group_new (void); -void gtk_accel_group_lock (GtkAccelGroup *accel_group); -void gtk_accel_group_unlock (GtkAccelGroup *accel_group); -void gtk_accel_group_connect (GtkAccelGroup *accel_group, - guint accel_key, - 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); -gboolean gtk_accel_groups_disconnect_closure (GClosure *closure); +GType gtk_accel_group_get_type (void); +GtkAccelGroup* gtk_accel_group_new (void); +void gtk_accel_group_lock (GtkAccelGroup *accel_group); +void gtk_accel_group_unlock (GtkAccelGroup *accel_group); +void gtk_accel_group_connect (GtkAccelGroup *accel_group, + guint accel_key, + GdkModifierType accel_mods, + GtkAccelFlags accel_flags, + GClosure *closure); +void gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group, + const gchar *accel_path, + GClosure *closure); +gboolean gtk_accel_group_disconnect (GtkAccelGroup *accel_group, + GClosure *closure); +gboolean gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group, + guint accel_key, + GdkModifierType accel_mods); /* --- GtkActivatable glue --- */ @@ -138,6 +141,10 @@ GtkAccelGroupEntry* gtk_accel_group_query (GtkAccelGroup *accel_group, guint accel_key, GdkModifierType accel_mods, guint *n_entries); + +void _gtk_accel_group_reconnect (GtkAccelGroup *accel_group, + GQuark accel_path_quark); + struct _GtkAccelGroupEntry { GtkAccelKey key; diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c index efa096fd35..b3721e1c4c 100644 --- a/gtk/gtkaccellabel.c +++ b/gtk/gtkaccellabel.c @@ -351,19 +351,21 @@ gtk_accel_label_expose_event (GtkWidget *widget, static void refetch_widget_accel_closure (GtkAccelLabel *accel_label) { - GSList *slist; - + GClosure *closure = NULL; + GList *clist, *list; + 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); + clist = gtk_widget_list_accel_closures (accel_label->accel_widget); + for (list = clist; list; list = list->next) + { + /* we just take the first closure used */ + closure = list->data; + break; + } + g_list_free (clist); + gtk_accel_label_set_accel_closure (accel_label, closure); } void diff --git a/gtk/gtkaccelmap.c b/gtk/gtkaccelmap.c index d99e01aacb..7fe375c606 100644 --- a/gtk/gtkaccelmap.c +++ b/gtk/gtkaccelmap.c @@ -42,7 +42,7 @@ typedef struct { guint std_accel_key; guint std_accel_mods; guint changed : 1; - GHookList *hooks; + GSList *groups; } AccelEntry; @@ -89,8 +89,8 @@ _gtk_accel_map_init (void) accel_entry_ht = g_hash_table_new (accel_entry_hash, accel_entry_equal); } -static gboolean -gtk_accel_path_is_valid (const gchar *accel_path) +gboolean +_gtk_accel_path_is_valid (const gchar *accel_path) { gchar *p; @@ -108,14 +108,13 @@ gtk_accel_path_is_valid (const gchar *accel_path) * @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", + * 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". @@ -123,18 +122,21 @@ gtk_accel_path_is_valid (const gchar *accel_path) * 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...". + * "<Gimp-Toolbox>/File/Dialogs/Tool Options...". */ -GQuark +void 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); + g_return_if_fail (_gtk_accel_path_is_valid (accel_path)); - accel_mods &= gtk_accelerator_get_default_mod_mask (); + if (!accel_key) + accel_mods = 0; + else + accel_mods &= gtk_accelerator_get_default_mod_mask (); entry = accel_path_lookup (accel_path); if (entry) @@ -159,154 +161,35 @@ gtk_accel_map_add_entry (const gchar *accel_path, 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 + * @returns: %TRUE if @accel_path is known, %FALSE otherwise * * 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 +gboolean 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); + g_return_val_if_fail (_gtk_accel_path_is_valid (accel_path), FALSE); 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? + key->accel_flags = 0; } - return entry ? g_quark_try_string (entry->accel_path) : 0; + return entry ? TRUE : FALSE; } static void @@ -340,9 +223,8 @@ internal_change_entry (const gchar *accel_path, { 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; + gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE; GQuark entry_quark; - GHook *hook; AccelEntry *entry = accel_path_lookup (accel_path); /* not much todo if there's no entry yet */ @@ -364,7 +246,7 @@ internal_change_entry (const gchar *accel_path, return FALSE; /* nobody's interested, easy going */ - if (!entry->hooks) + if (!entry->groups) { if (!simulate) { @@ -379,15 +261,8 @@ internal_change_entry (const gchar *accel_path, 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); - } + for (slist = entry->groups; slist; slist = slist->next) + g_hash_table_insert (group_hm, slist->data, slist->data); /* 2) collect acceleratables affected */ group_list = g_hash_table_slist_values (group_hm); @@ -408,62 +283,69 @@ internal_change_entry (const gchar *accel_path, 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; - } + if (accel_key) + for (slist = win_list; 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) + if (removable) + for (slist = group_list; 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++) { - can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED); - if (!can_change) + 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)); } - - 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; - } - + if (removable && can_change) + for (slist = replace_list; 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; + + /* ref accel groups */ + for (slist = group_list; slist; slist = slist->next) + g_object_ref (slist->data); /* 8) remove existing accelerators */ for (slist = replace_list; slist; slist = slist->next) @@ -475,25 +357,12 @@ internal_change_entry (const gchar *accel_path, 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); - } + for (slist = group_list; slist; slist = slist->next) + _gtk_accel_group_reconnect (slist->data, g_quark_from_string (entry->accel_path)); + + /* unref accel groups */ + for (slist = group_list; slist; slist = slist->next) + g_object_unref (slist->data); } g_slist_free (replace_list); g_slist_free (group_list); @@ -513,12 +382,9 @@ internal_change_entry (const gchar *accel_path, * 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 + * conflicts. A change will only occur if all conflicts could be resolved (which + * might not be the case if conflicting accelerators are locked). Succesful * 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, @@ -526,7 +392,7 @@ gtk_accel_map_change_entry (const gchar *accel_path, GdkModifierType accel_mods, gboolean replace) { - g_return_val_if_fail (gtk_accel_path_is_valid (accel_path), FALSE); + 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); } @@ -865,3 +731,34 @@ gtk_accel_map_add_filter (const gchar *filter_pattern) } accel_filters = g_slist_prepend (accel_filters, pspec); } + +void +_gtk_accel_map_add_group (const gchar *accel_path, + GtkAccelGroup *accel_group) +{ + AccelEntry *entry; + + g_return_if_fail (_gtk_accel_path_is_valid (accel_path)); + 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); + } + entry->groups = g_slist_prepend (entry->groups, accel_group); +} + +void +_gtk_accel_map_remove_group (const gchar *accel_path, + GtkAccelGroup *accel_group) +{ + AccelEntry *entry; + + entry = accel_path_lookup (accel_path); + g_return_if_fail (entry != NULL); + g_return_if_fail (g_slist_find (entry->groups, accel_group)); + + entry->groups = g_slist_remove (entry->groups, accel_group); +} diff --git a/gtk/gtkaccelmap.h b/gtk/gtkaccelmap.h index 99d0887ff3..7a59b2d808 100644 --- a/gtk/gtkaccelmap.h +++ b/gtk/gtkaccelmap.h @@ -26,13 +26,6 @@ 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, @@ -41,17 +34,10 @@ typedef void (*GtkAccelMapForeach) (gpointer data, /* --- public API --- */ -GQuark gtk_accel_map_add_entry (const gchar *accel_path, +void 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, +gboolean gtk_accel_map_lookup_entry (const gchar *accel_path, GtkAccelKey *key); gboolean gtk_accel_map_change_entry (const gchar *accel_path, guint accel_key, @@ -75,6 +61,12 @@ void gtk_accel_map_foreach_unfilterd (gpointer data, /* --- internal API --- */ void _gtk_accel_map_init (void); +void _gtk_accel_map_add_group (const gchar *accel_path, + GtkAccelGroup *accel_group); +void _gtk_accel_map_remove_group (const gchar *accel_path, + GtkAccelGroup *accel_group); +gboolean _gtk_accel_path_is_valid (const gchar *accel_path); + G_END_DECLS diff --git a/gtk/gtkitemfactory.c b/gtk/gtkitemfactory.c index 02fa3df2e6..a97abae70d 100644 --- a/gtk/gtkitemfactory.c +++ b/gtk/gtkitemfactory.c @@ -293,7 +293,7 @@ gtk_item_factory_add_foreign (GtkWidget *accel_widget, */ if (gtk_signal_lookup ("activate", GTK_OBJECT_TYPE (accel_widget))) { - if (accel_key && accel_group) + if (accel_group) { gtk_accel_map_add_entry (full_path, accel_key, accel_mods); _gtk_widget_set_accel_path (accel_widget, full_path, accel_group); diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 375b348c40..7a066aef4f 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -133,6 +133,9 @@ static void gtk_menu_reparent (GtkMenu *menu, static void gtk_menu_remove (GtkContainer *menu, GtkWidget *widget); +static void _gtk_menu_refresh_accel_paths (GtkMenu *menu, + gboolean group_changed); + static GtkMenuShellClass *parent_class = NULL; static const gchar *attach_data_key = "gtk-menu-attach-data"; @@ -866,8 +869,8 @@ gtk_menu_get_accel_group (GtkMenu *menu) * 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". + * "<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(). @@ -892,7 +895,7 @@ typedef struct { } AccelPropagation; static void -refresh_accel_paths_froeach (GtkWidget *widget, +refresh_accel_paths_foreach (GtkWidget *widget, gpointer data) { AccelPropagation *prop = data; @@ -904,7 +907,7 @@ refresh_accel_paths_froeach (GtkWidget *widget, prop->group_changed); } -void +static void _gtk_menu_refresh_accel_paths (GtkMenu *menu, gboolean group_changed) { @@ -917,7 +920,7 @@ _gtk_menu_refresh_accel_paths (GtkMenu *menu, prop.menu = menu; prop.group_changed = group_changed; gtk_container_foreach (GTK_CONTAINER (menu), - refresh_accel_paths_froeach, + refresh_accel_paths_foreach, &prop); } } diff --git a/gtk/gtkmenu.h b/gtk/gtkmenu.h index 225c9a90b2..cdd858a840 100644 --- a/gtk/gtkmenu.h +++ b/gtk/gtkmenu.h @@ -149,8 +149,6 @@ void gtk_menu_set_accel_group (GtkMenu *menu, 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/gtkwidget.c b/gtk/gtkwidget.c index b65e0d68fe..bb64921cf3 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2615,6 +2615,8 @@ gtk_widget_add_accelerator (GtkWidget *widget, closure = widget_new_accel_closure (widget, query.signal_id); + g_object_ref (widget); + /* install the accelerator. since we don't map this onto an accel_path, * the accelerator will automatically be locked. */ @@ -2622,10 +2624,11 @@ gtk_widget_add_accelerator (GtkWidget *widget, accel_key, accel_mods, accel_flags | GTK_ACCEL_LOCKED, - closure, - 0); + closure); g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); + + g_object_unref (widget); } /** @@ -2646,24 +2649,31 @@ gtk_widget_remove_accelerator (GtkWidget *widget, guint accel_mods) { GtkAccelGroupEntry *ag_entry; - GSList *slist; - guint n, i; + GList *slist, *clist; + guint n; 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) + clist = gtk_widget_list_accel_closures (widget); + for (slist = clist; slist; slist = slist->next) { - /* paranoid sanity checking */ + guint i; + for (i = 0; i < n; i++) if (slist->data == (gpointer) ag_entry[i].closure) { - gboolean is_removed = gtk_accel_groups_disconnect_closure (slist->data); + gboolean is_removed = gtk_accel_group_disconnect (accel_group, slist->data); + g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); + + g_list_free (clist); + return is_removed; } } + g_list_free (clist); g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)", accel_key, accel_mods, accel_group, @@ -2672,73 +2682,48 @@ gtk_widget_remove_accelerator (GtkWidget *widget, return FALSE; } -GSList* -_gtk_widget_get_accel_closures (GtkWidget *widget) +/** + * gtk_widget_list_accel_closures + * @widget: widget to list accelerator closures for + * @returns: a newly allocated #GList of closures + * + * List the closures used by @widget for accelerator group connections + * with gtk_accel_group_connect_by_path() or gtk_accel_group_connect(). + * The closures can be used to monitor accelerator changes on @widget, + * by connecting to the ::accel_changed signal of the #GtkAccelGroup + * of a closure which can be found out with gtk_accel_group_from_accel_closure(). + */ +GList* +gtk_widget_list_accel_closures (GtkWidget *widget) { + GSList *slist; + GList *clist = NULL; + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - return g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); + for (slist = g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); slist; slist = slist->next) + if (gtk_accel_group_from_accel_closure (slist->data)) + clist = g_list_prepend (clist, slist->data); + return clist; } typedef struct { + GQuark path_quark; 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) { AccelPath *apath = data; - /* stop notification */ - gtk_accel_map_remove_notifer (apath->path, apath, accel_path_changed); + gtk_accel_group_disconnect (apath->accel_group, apath->closure); - /* 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); - } + /* closures_destroy takes care of unrefing the closure */ g_object_unref (apath->accel_group); + g_free (apath); } @@ -2753,25 +2738,21 @@ _gtk_widget_set_accel_path (GtkWidget *widget, GtkAccelGroup *accel_group) { AccelPath *apath; - GtkAccelKey key; g_return_if_fail (GTK_IS_WIDGET (widget)); 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) { - GQuark quark_path = gtk_accel_map_add_entry (accel_path, 0, 0); - - if (!quark_path) - return; /* pathologic anyway */ + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); + g_return_if_fail (_gtk_accel_path_is_valid (accel_path)); + gtk_accel_map_add_entry (accel_path, 0, 0); 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; + apath->path_quark = g_quark_from_string (accel_path); + apath->closure = widget_new_accel_closure (apath->widget, GTK_WIDGET_GET_CLASS (apath->widget)->activate_signal); } else apath = NULL; @@ -2780,14 +2761,9 @@ _gtk_widget_set_accel_path (GtkWidget *widget, 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); + gtk_accel_group_connect_by_path (apath->accel_group, g_quark_to_string (apath->path_quark), apath->closure); - /* 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); - } + g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); } const gchar* @@ -2798,7 +2774,7 @@ _gtk_widget_get_accel_path (GtkWidget *widget) g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path); - return apath ? apath->path : NULL; + return apath ? g_quark_to_string (apath->path_quark) : NULL; } gboolean diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index ee464fa436..08940458b0 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -492,7 +492,7 @@ 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); +GList* gtk_widget_list_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 27c5eed10d..1039a577ea 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -46,7 +46,7 @@ enum { ACTIVATE_FOCUS, ACTIVATE_DEFAULT, MOVE_FOCUS, - ACCELS_CHANGED, + KEYS_CHANGED, LAST_SIGNAL }; @@ -222,7 +222,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 void gtk_window_notify_keys_changed (GtkWindow *window); static GSList *toplevel_list = NULL; static GHashTable *mnemonic_hash_table = NULL; @@ -350,7 +350,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; + klass->keys_changed = NULL; /* Construct */ g_object_class_install_property (gobject_class, @@ -500,11 +500,11 @@ gtk_window_class_init (GtkWindowClass *klass) 1, GTK_TYPE_DIRECTION_TYPE); - window_signals[ACCELS_CHANGED] = - g_signal_new ("accels_changed", + window_signals[KEYS_CHANGED] = + g_signal_new ("keys_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - GTK_SIGNAL_OFFSET (GtkWindowClass, accels_changed), + GTK_SIGNAL_OFFSET (GtkWindowClass, keys_changed), NULL, NULL, gtk_marshal_VOID__VOID, G_TYPE_NONE, @@ -1042,30 +1042,30 @@ gtk_window_set_policy (GtkWindow *window, } static gboolean -handle_accels_changed (gpointer data) +handle_keys_changed (gpointer data) { GtkWindow *window; GDK_THREADS_ENTER (); window = GTK_WINDOW (data); - if (window->accels_changed_handler) + if (window->keys_changed_handler) { - gtk_idle_remove (window->accels_changed_handler); - window->accels_changed_handler = 0; + gtk_idle_remove (window->keys_changed_handler); + window->keys_changed_handler = 0; } - g_signal_emit (window, window_signals[ACCELS_CHANGED], 0); + g_signal_emit (window, window_signals[KEYS_CHANGED], 0); GDK_THREADS_LEAVE (); return FALSE; } static void -gtk_window_notify_accels_changed (GtkWindow *window) +gtk_window_notify_keys_changed (GtkWindow *window) { - if (!window->accels_changed_handler) - window->accels_changed_handler = gtk_idle_add (handle_accels_changed, window); + if (!window->keys_changed_handler) + window->keys_changed_handler = gtk_idle_add (handle_keys_changed, window); } /** @@ -1078,15 +1078,15 @@ gtk_window_notify_accels_changed (GtkWindow *window) * in @accel_group. **/ void -gtk_window_add_accel_group (GtkWindow *window, - GtkAccelGroup *accel_group) +gtk_window_add_accel_group (GtkWindow *window, + GtkAccelGroup *accel_group) { g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (accel_group != NULL); + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); _gtk_accel_group_attach (accel_group, G_OBJECT (window)); g_signal_connect_object (accel_group, "accel_changed", - G_CALLBACK (gtk_window_notify_accels_changed), + G_CALLBACK (gtk_window_notify_keys_changed), window, G_CONNECT_SWAPPED); } @@ -1098,14 +1098,14 @@ gtk_window_add_accel_group (GtkWindow *window, * Reverses the effects of gtk_window_add_accel_group(). **/ void -gtk_window_remove_accel_group (GtkWindow *window, - GtkAccelGroup *accel_group) +gtk_window_remove_accel_group (GtkWindow *window, + GtkAccelGroup *accel_group) { g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (accel_group != NULL); g_signal_handlers_disconnect_by_func (accel_group, - G_CALLBACK (gtk_window_notify_accels_changed), + G_CALLBACK (gtk_window_notify_keys_changed), window); _gtk_accel_group_detach (accel_group, G_OBJECT (window)); } @@ -1137,7 +1137,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); + gtk_window_notify_keys_changed (window); } void @@ -1163,7 +1163,7 @@ gtk_window_remove_mnemonic (GtkWindow *window, g_hash_table_remove (mnemonic_hash_table, mnemonic); g_free (mnemonic); } - gtk_window_notify_accels_changed (window); + gtk_window_notify_keys_changed (window); } gboolean @@ -1231,7 +1231,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); + gtk_window_notify_keys_changed (window); } /** @@ -2929,10 +2929,10 @@ gtk_window_finalize (GObject *object) g_free (window->geometry_info); } - if (window->accels_changed_handler) + if (window->keys_changed_handler) { - gtk_idle_remove (window->accels_changed_handler); - window->accels_changed_handler = 0; + gtk_idle_remove (window->keys_changed_handler); + window->keys_changed_handler = 0; } G_OBJECT_CLASS (parent_class)->finalize (object); diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 3a6dd6de9e..2ebfaea759 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -105,7 +105,7 @@ struct _GtkWindow guint frame_right; guint frame_bottom; - guint accels_changed_handler; + guint keys_changed_handler; GdkModifierType mnemonic_modifier; gpointer gtk_reserved1; /* For future GdkScreen * */ @@ -126,7 +126,7 @@ struct _GtkWindowClass void (* activate_default) (GtkWindow *window); void (* move_focus) (GtkWindow *window, GtkDirectionType direction); - void (*accels_changed) (GtkWindow *window); + void (*keys_changed) (GtkWindow *window); }; #define GTK_TYPE_WINDOW_GROUP (gtk_window_group_get_type ()) |