With the same color code as the fader automation button on mixer strips.
This is especially usefull when use_knob is true (e.g. for a-EQ) because
the automation only shows one letter and a "Write" state can thus be
easy to miss.
If for whatever reason a grab is taken (e.g. a menu popping up) while
somebody is pressing a mouse button on an ArdourButton, then the
ArdourButton will not get the mouse button release event and will look
stuck in pressed position.
The leave notify event is fired if the mouse is still on the
ArdourButton while the grab is taken, but not if the user was dragging
the mouse outside of the button.
The only reliable way is to listen for the grab_broken_event signal.
Do so.
Make their popup menus show attached, and on mouse down, but keep the
context menu behavior on middle- and right-click for the group button
that reacted to those (probably an oversight but some users might have
got the habit of right-clicking).
This also makes the group deletion on Ctrl+click happen on mouse down
instead of mouse up which is not a great difference and avoids
complicating the code.
By passing the current text of the automation button we can make the
dropdown menu align with the current mode. This will only work for
full-size automation buttons, not when use-knob is true, but in that
case it feels wrong to popup on top of the button anyway.
Also make the menu show on mouse down like a real dropdown.
The code computing the position of the popup menu used to compare the
given string to each MenuItem::get_label() result, but that method
actually replaces the content (child) of the MenuItem if that child is
not already a Gtk::Label. In particular, this breaks menu separators.
Avoid the issue by checking by hand if the only child of the MenuItem is
a Label, and directly compare the label text.
Because all uses of the function positioning menus anchored to a widget
were as callback argument to Gtk::Menu::popup() where the caller needed
to correctly bind arguments, this led to repeated and a bit obscure code.
Wrap the logic into an helper function that takes care of all that, and
update the callers.
This mostly fixes an issue with notifying plugins about tempo-ramps
and BPM changes.
remaining to be fixed (in tempo.h):
```
_session.tempo_map().metric_at(frame_position).tempo().beats_per_minute()
```
currently returns the most recent *fixed* tempo at or before
`frame_position`. All other Plugin types are affected by this as well.