From 9a11e3a64d485f2e9ae2bb2dd6409eb1c87f99d0 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 15 Mar 2016 12:34:26 -0400 Subject: change API for CairoWidget::focus_handler This functor/closure is responsible for stealing focus from any existing text entry (or whatever else may have focus) when clicking on a CairoWidget or derived class. The old implementation just gave focus back to the editor canvas. The new version walks up the widget packing heirarchy to find a focusable parent (from the CairoWidget for which it is invoked). If no focusable parent is found, it cancels keyboard focus in the toplevel window containing the CairoWidget --- gtk2_ardour/ardour_button.cc | 2 +- gtk2_ardour/big_clock_window.cc | 3 +-- gtk2_ardour/editor.cc | 2 +- gtk2_ardour/editor.h | 2 +- gtk2_ardour/editor_actions.cc | 35 +++++++++++++++++++++++++++++++-- gtk2_ardour/editor_mouse.cc | 2 +- gtk2_ardour/public_editor.h | 2 +- libs/gtkmm2ext/cairo_widget.cc | 6 +++--- libs/gtkmm2ext/gtkmm2ext/cairo_widget.h | 4 ++-- 9 files changed, 44 insertions(+), 14 deletions(-) diff --git a/gtk2_ardour/ardour_button.cc b/gtk2_ardour/ardour_button.cc index a4f346a040..2d020595ab 100644 --- a/gtk2_ardour/ardour_button.cc +++ b/gtk2_ardour/ardour_button.cc @@ -724,7 +724,7 @@ ArdourButton::set_led_left (bool yn) bool ArdourButton::on_button_press_event (GdkEventButton *ev) { - focus_handler (); + focus_handler (this); if (ev->button == 1 && (_elements & Indicator) && _led_rect && _distinct_led_click) { if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width && diff --git a/gtk2_ardour/big_clock_window.cc b/gtk2_ardour/big_clock_window.cc index e442c5455b..56fe34feac 100644 --- a/gtk2_ardour/big_clock_window.cc +++ b/gtk2_ardour/big_clock_window.cc @@ -55,8 +55,7 @@ void BigClockWindow::on_unmap () { ArdourWindow::on_unmap (); - - PublicEditor::instance().reset_focus (); + PublicEditor::instance().reset_focus (&clock); } bool diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index a118d1d642..1df263496b 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1178,7 +1178,7 @@ Editor::generic_event_handler (GdkEvent* ev) /* leaving window, so reset focus, thus ending any and all text entry operations. */ - reset_focus(); + reset_focus (&contents()); break; } break; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 1d11dd282d..5778a3cbbb 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1274,7 +1274,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void naturalize_region (); - void reset_focus (); + void reset_focus (Gtk::Widget*); void split_region (); diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 008a4d75dc..280bc3f9cb 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -1739,9 +1739,40 @@ Editor::parameter_changed (std::string p) } void -Editor::reset_focus () +Editor::reset_focus (Gtk::Widget* w) { - _track_canvas->grab_focus(); + /* this resets focus to the first focusable parent of the given widget, + * or, if there is no focusable parent, cancels focus in the toplevel + * window that the given widget is packed into (if there is one). + */ + + if (!w) { + return; + } + + Gtk::Widget* top = w->get_toplevel(); + + if (!top || !top->is_toplevel()) { + return; + } + + w = w->get_parent (); + + while (w) { + if (w->get_can_focus ()) { + Window* win = dynamic_cast (top); + win->set_focus (*w); + return; + } + w = w->get_parent (); + } + + /* no focusable parent found, cancel focus in top level window. + C++ API cannot be used for this. Thanks, references. + */ + + gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0); + } void diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 48d838a1db..a1a7b793b6 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2456,7 +2456,7 @@ Editor::escape () selection->clear (); } - reset_focus (); + reset_focus (&contents()); } /** Update _join_object_range_state which indicate whether we are over the top diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index df6bba3a06..45fbb9ece9 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -319,7 +319,7 @@ class PublicEditor : public Gtkmm2ext::Tabbable { Glib::RefPtr editor_menu_actions; Glib::RefPtr _region_actions; - virtual void reset_focus () = 0; + virtual void reset_focus (Gtk::Widget*) = 0; virtual bool canvas_scroll_event (GdkEventScroll* event, bool from_canvas) = 0; virtual bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) = 0; diff --git a/libs/gtkmm2ext/cairo_widget.cc b/libs/gtkmm2ext/cairo_widget.cc index 78fb042f59..fe93f1eb7c 100644 --- a/libs/gtkmm2ext/cairo_widget.cc +++ b/libs/gtkmm2ext/cairo_widget.cc @@ -30,7 +30,7 @@ static const char* has_cairo_widget_background_info = "has_cairo_widget_backgrou bool CairoWidget::_flat_buttons = false; bool CairoWidget::_widget_prelight = true; -sigc::slot CairoWidget::focus_handler; +sigc::slot CairoWidget::focus_handler; void CairoWidget::set_source_rgb_a( cairo_t* cr, Gdk::Color col, float a) //ToDo: this one and the Canvas version should be in a shared file (?) { @@ -60,7 +60,7 @@ CairoWidget::~CairoWidget () bool CairoWidget::on_button_press_event (GdkEventButton*) { - focus_handler(); + focus_handler (this); return false; } @@ -393,7 +393,7 @@ CairoWidget::set_widget_prelight (bool yn) } void -CairoWidget::set_focus_handler (sigc::slot s) +CairoWidget::set_focus_handler (sigc::slot s) { focus_handler = s; } diff --git a/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h b/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h index 2a483840f9..2588adcdcc 100644 --- a/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h +++ b/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h @@ -93,7 +93,7 @@ public: they wish to invoke any existing focus handler from their own button press handler, they can just use: focus_handler(); */ - static void set_focus_handler (sigc::slot); + static void set_focus_handler (sigc::slot); protected: /** Render the widget to the given Cairo context */ @@ -118,7 +118,7 @@ protected: static bool _widget_prelight; bool _grabbed; - static sigc::slot focus_handler; + static sigc::slot focus_handler; private: Cairo::RefPtr image_surface; -- cgit v1.2.3