applied patch from owen to get rid of accel map notifiers. changed things

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.
This commit is contained in:
Tim Janik 2001-11-20 23:43:03 +00:00 committed by Tim Janik
parent 9ea603f15d
commit 9800f731e0
25 changed files with 942 additions and 534 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -64,16 +64,39 @@ 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:
<!-- ##### FUNCTION gtk_accel_group_disconnect_key ##### -->
<para>
</para>
@accel_group:
@accel_key:
@accel_mods:
@ -92,19 +115,6 @@ An object representing and maintaining a group of accelerators.
@Returns:
<!-- ##### FUNCTION gtk_accel_groups_activate ##### -->
<para>
</para>
@acceleratable:
@accel_key:
@accel_mods:
@Returns:
<!-- # Unused Parameters # -->
@object:
<!-- ##### FUNCTION gtk_accel_group_lock ##### -->
<para>
@ -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>

View File

@ -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>

View File

@ -530,6 +530,15 @@ GtkWidget
@Returns:
<!-- ##### FUNCTION gtk_widget_list_accel_closures ##### -->
<para>
</para>
@widget:
@Returns:
<!-- ##### FUNCTION gtk_widget_event ##### -->
<para>

View File

@ -694,13 +694,6 @@ it's larger
@height:
<!-- ##### SIGNAL GtkWindow::accels-changed ##### -->
<para>
</para>
@window: the object which received the signal.
<!-- ##### SIGNAL GtkWindow::activate-default ##### -->
<para>
@ -724,6 +717,13 @@ it's larger
@event:
@Returns:
<!-- ##### SIGNAL GtkWindow::keys-changed ##### -->
<para>
</para>
@window: the object which received the signal.
<!-- ##### SIGNAL GtkWindow::move-focus ##### -->
<para>

View File

@ -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);
/* tag closure for backwards lookup */
g_closure_add_invalidate_notifier (closure, accel_group, accel_tag_func);
/* 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);
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);
if (gtk_accel_map_lookup_entry (accel_path, &key))
{
accel_key = key.accel_key;
accel_mods = key.accel_mods;
}
removed_some = TRUE;
}
g_slist_free (clist);
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 "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
* "&lt;Release&gt;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 "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
*
* 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 "&lt;Control&gt;q".
*
* The caller of this function must free the returned string.
*/

View File

@ -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;

View File

@ -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

View File

@ -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 "&lt;WINDOWTYPE&gt;/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...".
* "&lt;Gimp-Toolbox&gt;/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;
}
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 (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))
{
can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
if (!can_change)
goto break_loop_step5;
seen_accel = TRUE;
break;
}
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));
}
}
removable = !seen_accel;
/* 5) walk all accel groups and search for locks */
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++)
{
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);
}

View File

@ -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

View File

@ -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);

View File

@ -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".
* "&lt;Gnumeric-Sheet&gt;/File"); has been called, assign its items the accel paths:
* "&lt;Gnumeric-Sheet&gt;/File/New" and "&lt;Gnumeric-Sheet&gt;/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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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 ())