Make ArdourButton detect when a grab should stop being pressed
authorJulien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
Thu, 18 Aug 2016 14:09:50 +0000 (16:09 +0200)
committerJulien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
Thu, 18 Aug 2016 14:16:17 +0000 (16:16 +0200)
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.

gtk2_ardour/ardour_button.cc
gtk2_ardour/ardour_button.h

index 56854880d851c69285d5008e4099cfc67c99c132..ae9eb310d5c32f8464265444700e8308f5f67e17 100644 (file)
@@ -97,6 +97,8 @@ ArdourButton::ArdourButton (Element e)
        , _pattern_height (0)
 {
        UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
+       /* This is not provided by gtkmm */
+       signal_grab_broken_event().connect (sigc::mem_fun (*this, &ArdourButton::on_grab_broken_event));
 }
 
 ArdourButton::ArdourButton (const std::string& str, Element e)
@@ -140,6 +142,8 @@ ArdourButton::ArdourButton (const std::string& str, Element e)
        set_text (str);
        UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ArdourButton::color_handler));
        UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ArdourButton::on_name_changed));
+       /* This is not provided by gtkmm */
+       signal_grab_broken_event().connect (sigc::mem_fun (*this, &ArdourButton::on_grab_broken_event));
 }
 
 ArdourButton::~ArdourButton()
@@ -1060,6 +1064,16 @@ ArdourButton::on_leave_notify_event (GdkEventCrossing* ev)
        return CairoWidget::on_leave_notify_event (ev);
 }
 
+bool
+ArdourButton::on_grab_broken_event(GdkEventGrabBroken* grab_broken_event) {
+       /* Our implicit grab due to a button_press was broken by another grab:
+        * the button will not get any button_release event if the mouse leaves
+        * while the grab is taken, so unpress ourselves */
+       _grabbed = false;
+       CairoWidget::set_dirty ();
+       return true;
+}
+
 void
 ArdourButton::set_tweaks (Tweaks t)
 {
index 78c2f5e369ae7f5bed1ab125e78bb9d978a189cb..1128dce97a61500c9584932705a3a645783a4b61 100644 (file)
@@ -124,6 +124,7 @@ class ArdourButton : public CairoWidget , public Gtkmm2ext::Activatable
        void on_realize ();
        bool on_enter_notify_event (GdkEventCrossing*);
        bool on_leave_notify_event (GdkEventCrossing*);
+       bool on_grab_broken_event(GdkEventGrabBroken*);
        bool on_focus_in_event (GdkEventFocus*);
        bool on_focus_out_event (GdkEventFocus*);
        bool on_key_release_event (GdkEventKey *);