We were pretty aggressive about not registering
observers further than necessary, stopping at the
first muxer that provides an action.
But even though action changes further up in the tree
won't be relevant in that case, we need to listen to
accel changes, since they may come from higher up
in the tree (e.g. when using
gtk_application_set_accels_for_action with an action
that is defined on a widget.
So, register all the way to the top, and stop propagating
action changes when we hit a muxer that provides the action.
If set to TRUE, does not call the free func for the removed items.
This can be used to move items between arrays without having to do the
refcounting dance.
Instead of implementing the GActionGroup interface
and using its signals for propagating changes up
and down the muxer hierarchy, use the GtkActionObserver
mechanism. This cuts down on the signal emission
overhead.
No need to construct a detailed signal name for
every action when we can just look up the signal ID
once and use the quark that the GParamSpec already
has. Also, we don't need to loop over the actions
every time we get a notification.
We were having a problem where property actions were
not getting state updates because prop_actions_connect
was triggered from some instance_init function while
the widget class is not in place yet.
Delay that call until the widget is fully constructed,
so we can guarantee that we are dealing with the
correct class private struct, and see all class actions.
We need to cleanup state here immediately so that we do not potentially
access the g_class private data after it been finalized. This ensures that
the borrowed reference is dropped by the muxer.
Before this commit, adding GtkWidgetAction to class private data would
require copying the actions to each subclass as they were built or
modified. This was convenient in that it is a sort of "copy on write"
semantic.
However, due to the way that GTypeInstance works with base _init()
functions, the "g_class" pointer in GTypeInstance is updated as each
_init() function is called. That means you cannot access the subclasses
class private data, but only the parent class private data.
If instead we use a singly linked list of GtkWidgetAction, each subclass
has their own "head" yet all subclasses share the tail of the
GtkWidgetAction chain.
This creates one bit of complexity though. You need a stable way to know
which "bit" is the "enabled" bit of the action so we can track enabled
GAction state. That is easily solved by calculating the distance to the
end of the chain for a given action so that base classes sort ahead of
subclasses. Since the parent class always knows its parent's actions, the
position is stable.
A new dynamic bitarray helper also helps us avoid allocations in all the
current cases (up to 64 actions per widget) and dynamically switches to
malloc if that is to ever be exceeded.
I've seen a crash when the action muxer gets
disposed during widget destroy, and tries to
disconnect from widget signals too late.
There is no real need to disconnect, since the
only time an action muxer is going away is when
its widget is destroyed, so just don't do it.
Previously, we would not look any further for
an action once we found a match for the prefix,
defining inheritance by groups. Change this to
inheritance for individual actions, since we
are moving towards individual actions as the
main ingredient in GTKs action support.
The only cases of stateful actions we've seen
so far have been boolean properties, and we
don't really want to add much state handling
API, so lets just go with property actions
for now.
Adapt the only user in GtkText.
Add a facility to register and install actions
at class init time. The intended use for these
actions is for
a) context and other model-based menus
b) key bindings
Most of these actions are going to be stateless,
so add separate apis for the simple and stateful
cases.
We avoid creating an action group for these by
teaching the action muxer about these actions.
The action muxer also maintains the enabled
state for these actions.
Instead of duplicating this code in multiple places,
add an api to look up an action group for a prefixed
name, and return the unprefixed name at the same time.
This adds specific marshallers for all of the locations where a generic
marshaller is being used. It also provides va_marshallers to reduce the
chances that we get stack traces from perf going through ffi_call_unix64.
This is forward ported from gtk-3-24.
# Conflicts:
# gtk/gtkeventcontrollerkey.c
# gtk/gtkeventcontrollermotion.c
# gtk/gtkgesture.c
# gtk/gtkgesturemultipress.c
These functions, while added for use by the GTK inspector, are generally
useful to applications that need to resolve what action groups are
available to a particular GtkWidget.
https://bugzilla.gnome.org/show_bug.cgi?id=741386