Window focus handling fixes.
authornick_m <mainsbridge@gmail.com>
Wed, 1 Apr 2015 15:41:49 +0000 (02:41 +1100)
committernick_m <mainsbridge@gmail.com>
Wed, 1 Apr 2015 15:41:49 +0000 (02:41 +1100)
Many windows were not getting key events.
Use magic focus infrastructure (built for widgets) to deliver key events
via window focus in/out.

gtk2_ardour/ardour_dialog.cc
gtk2_ardour/ardour_dialog.h
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_window.cc
gtk2_ardour/ardour_window.h
gtk2_ardour/export_video_dialog.cc
gtk2_ardour/export_video_dialog.h
gtk2_ardour/keyeditor.cc
gtk2_ardour/plugin_ui.cc
libs/gtkmm2ext/gtkmm2ext/keyboard.h
libs/gtkmm2ext/keyboard.cc

index 37327b2c91e34bdf739f38334923d2a20e6cb27f..423cab0a30dd466c7ed0c6fc5d7bc00e98b70dc6 100644 (file)
@@ -64,31 +64,37 @@ ArdourDialog::~ArdourDialog ()
 }
 
 bool
-ArdourDialog::on_key_press_event (GdkEventKey* ev)
+ArdourDialog::on_focus_in_event (GdkEventFocus *ev)
 {
-       if (!relay_key_press (ev, this)) {
-               return Gtk::Window::on_key_press_event(ev);
+       if (Keyboard::some_magic_widget_has_focus()) {
+               Keyboard::magic_widget_drop_focus ();
        }
-       return true;
-}
 
-bool
-ArdourDialog::on_enter_notify_event (GdkEventCrossing *ev)
-{
-       Keyboard::the_keyboard().enter_window (ev, this);
-       return Dialog::on_enter_notify_event (ev);
+       Keyboard::the_keyboard().focus_in_window (ev, this);
+       Keyboard::magic_widget_grab_focus ();
+       return Dialog::on_focus_in_event (ev);
 }
 
 bool
-ArdourDialog::on_leave_notify_event (GdkEventCrossing *ev)
+ArdourDialog::on_focus_out_event (GdkEventFocus *ev)
 {
-       Keyboard::the_keyboard().leave_window (ev, this);
-       return Dialog::on_leave_notify_event (ev);
+       if (!get_modal()) {
+               Keyboard::magic_widget_drop_focus ();
+               Keyboard::the_keyboard().focus_out_window (ev, this);
+       }
+       return Dialog::on_focus_out_event (ev);
 }
 
 void
 ArdourDialog::on_unmap ()
 {
+       if (Keyboard::some_magic_widget_has_focus()) {
+               Gtk::Window* win = static_cast<Gtk::Window*>(get_focus()->get_toplevel());
+               if (win == Keyboard::get_current_window()) {
+                       Keyboard::magic_widget_drop_focus ();
+               }
+       }
+
        Keyboard::the_keyboard().leave_window (0, this);
        Dialog::on_unmap ();
 }
@@ -119,7 +125,7 @@ void
 ArdourDialog::init ()
 {
        set_border_width (10);
-
+       add_events (Gdk::FOCUS_CHANGE_MASK);
        set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
 
        Gtk::Window* parent = WM::Manager::instance().transient_parent();
index d994c0a6d110ce37fa23de8b4df6fc574a444579..1224cbb00a0b19298dd965fd30cf2ddeeb530c5b 100644 (file)
@@ -42,10 +42,9 @@ class ArdourDialog : public Gtk::Dialog, public ARDOUR::SessionHandlePtr
        ArdourDialog (Gtk::Window& parent, std::string title, bool modal = false, bool use_separator = false);
        ~ArdourDialog();
 
-       bool on_enter_notify_event (GdkEventCrossing*);
-       bool on_leave_notify_event (GdkEventCrossing*);
+       bool on_focus_in_event (GdkEventFocus*);
+       bool on_focus_out_event (GdkEventFocus*);
         bool on_delete_event (GdkEventAny*);
-        bool on_key_press_event (GdkEventKey*);
        void on_unmap ();
        void on_show ();
 
index 5d1da0dfcdbe00184c8de8d44eb7b9d249065b24..4d38d71c8564e5d0b01169fd73d2651275e3e520 100644 (file)
@@ -2623,10 +2623,8 @@ ARDOUR_UI::edit_metadata ()
 {
        SessionMetadataEditor dialog;
        dialog.set_session (_session);
-       Keyboard::magic_widget_grab_focus ();
        dialog.grab_focus ();
        dialog.run ();
-       Keyboard::magic_widget_drop_focus ();
 }
 
 void
index 3bc80dfc46ee89a151cbdcf435aa4e9edec0b6ad..fc3ec84b0e30f765626c3cd297376d0b385207b3 100644 (file)
@@ -58,26 +58,48 @@ ArdourWindow::~ArdourWindow ()
 bool
 ArdourWindow::on_key_press_event (GdkEventKey* ev)
 {
-       return relay_key_press (ev, this);
+       if (get_modal()) {
+               return Gtk::Window::on_key_press_event (ev);
+       }
+
+       if (!relay_key_press (ev, this)) {
+               return Gtk::Window::on_key_press_event (ev);
+       }
+       return true;
 }
 
 bool
-ArdourWindow::on_enter_notify_event (GdkEventCrossing *ev)
+ArdourWindow::on_focus_in_event (GdkEventFocus *ev)
 {
-       Keyboard::the_keyboard().enter_window (ev, this);
-       return Window::on_enter_notify_event (ev);
+       if (Keyboard::some_magic_widget_has_focus()) {
+               Keyboard::magic_widget_drop_focus ();
+       }
+
+       Keyboard::the_keyboard().focus_in_window (ev, this);
+       Keyboard::magic_widget_grab_focus ();
+       return Window::on_focus_in_event (ev);
 }
 
 bool
-ArdourWindow::on_leave_notify_event (GdkEventCrossing *ev)
+ArdourWindow::on_focus_out_event (GdkEventFocus *ev)
 {
-       Keyboard::the_keyboard().leave_window (ev, this);
-       return Window::on_leave_notify_event (ev);
+       if (!get_modal()) {
+               Keyboard::magic_widget_drop_focus ();
+               Keyboard::the_keyboard().focus_out_window (ev, this);
+       }
+       return Window::on_focus_out_event (ev);
 }
 
 void
 ArdourWindow::on_unmap ()
 {
+       if (Keyboard::some_magic_widget_has_focus()) {
+               Gtk::Window* win = static_cast<Gtk::Window*>(get_focus()->get_toplevel());
+               if (win == Keyboard::get_current_window()) {
+                       Keyboard::magic_widget_drop_focus ();
+               }
+       }
+
        Keyboard::the_keyboard().leave_window (0, this);
        Window::on_unmap ();
 }
@@ -92,8 +114,9 @@ void
 ArdourWindow::init ()
 {
        set_border_width (10);
+       add_events (Gdk::FOCUS_CHANGE_MASK);
 
-        /* ArdourWindows are not dialogs (they have no "OK" or "Close" button) but
+      /* ArdourWindows are not dialogs (they have no "OK" or "Close" button) but
            they should be considered part of the same "window level" as a dialog. This
            works on X11 and Quartz, in that:
            
index c90eb3c049103b3fbdb663cf22dc1deafcf7d634..7ae9c3dbce205b52ddbd472e232710293d7d61b6 100644 (file)
@@ -44,8 +44,8 @@ class ArdourWindow : public Gtk::Window, public ARDOUR::SessionHandlePtr, public
        ArdourWindow (Gtk::Window& parent, std::string title);
        ~ArdourWindow();
 
-       bool on_enter_notify_event (GdkEventCrossing*);
-       bool on_leave_notify_event (GdkEventCrossing*);
+       bool on_focus_in_event (GdkEventFocus*);
+       bool on_focus_out_event (GdkEventFocus*);
         bool on_delete_event (GdkEventAny *);
         bool on_key_press_event (GdkEventKey*);
        void on_unmap ();
index 7e01f5b9ad1a132eb4e6e37114bbb0c087262bce..e8b823dc90f92d166e6cf0316751ff649e27df51 100644 (file)
@@ -536,22 +536,6 @@ ExportVideoDialog::on_show ()
        Dialog::on_show ();
 }
 
-bool
-ExportVideoDialog::on_focus_in_event (GdkEventFocus *ev)
-{
-       Dialog::on_focus_in_event (ev);
-       Gtkmm2ext::Keyboard::magic_widget_grab_focus ();
-       return true;
-}
-
-bool
-ExportVideoDialog::on_focus_out_event (GdkEventFocus *ev)
-{
-       Dialog::on_focus_out_event (ev);
-       Gtkmm2ext::Keyboard::magic_widget_drop_focus ();
-       return true;
-}
-
 void
 ExportVideoDialog::abort_clicked ()
 {
index ab6f3223e92c089b08d5e5067c6e743bc60b60b8..93fe7fb5c2072df2ae031cd6e01f82e3f873b115 100644 (file)
@@ -64,9 +64,6 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList
 
        void set_original_file_information ();
 
-       bool on_focus_in_event (GdkEventFocus*);
-       bool on_focus_out_event (GdkEventFocus*);
-
        void open_outfn_dialog ();
        void open_invid_dialog ();
        void scale_checkbox_toggled ();
index f8b5f2da4e945062004d53f2b950dc0187d46221..28cd8b8508f0edc2bbae6d82abdf6c5943927db4 100644 (file)
@@ -184,7 +184,7 @@ KeyEditor::on_key_press_event (GdkEventKey* ev)
        if (!ev->is_modifier) {
                last_keyval = ev->keyval;
        }
-       return false;
+       return ArdourWindow::on_key_press_event (ev);
 }
 
 bool
index ea9dfaec75d4cdd66279043269f059b4db0a6692..9f22d1b54c68561d14a56f9e0c69ab04e15f1852 100644 (file)
@@ -357,7 +357,10 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
                        if (_pluginui->non_gtk_gui()) {
                                _pluginui->forward_key_event (event);
                        } else {
-                               return relay_key_press (event, this);
+                               if (!relay_key_press (event, this)) {
+                                       return Window::on_key_press_event (event);
+                               }
+                               return true;
                        }
                }
                return true;
@@ -376,7 +379,10 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
                                */
                                return relay_key_press (event, &PublicEditor::instance());
                        } else {
-                               return relay_key_press (event, this);
+                               if (!relay_key_press (event, this)) {
+                                       return Window::on_key_press_event (event);
+                               }
+                               return true;
                        }
                } else {
                        return false;
index d756c6199eac8f54814d793582330bf9977179c9..328638373fc3f6ab12bc7d9db0deafa11bfcbc9b 100644 (file)
@@ -106,6 +106,8 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
 
        bool leave_window (GdkEventCrossing *ev, Gtk::Window*);
        bool enter_window (GdkEventCrossing *ev, Gtk::Window*);
+       bool focus_in_window (GdkEventFocus *ev, Gtk::Window*);
+       bool focus_out_window (GdkEventFocus *ev, Gtk::Window*);
 
        static bool modifier_state_contains (guint state, ModifierMask);
        static bool modifier_state_equals   (guint state, ModifierMask);
@@ -146,6 +148,7 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
        static bool some_magic_widget_has_focus ();
        static void magic_widget_grab_focus ();
        static void magic_widget_drop_focus ();
+       static Gtk::Window* get_current_window () { return current_window; };
 
        static void close_current_dialog ();
 
index 48fcae8482d5a28128c7cc02f22c1807068972d2..420d42209b3311bffeff5d4aea6790d2d6b38e61 100644 (file)
@@ -384,6 +384,29 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* /*win*/)
        return false;
 }
 
+bool
+Keyboard::focus_in_window (GdkEventFocus *, Gtk::Window* win)
+{
+       current_window = win;
+       DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Focusing in window, title = %1\n", win->get_title()));
+       return false;
+}
+
+bool
+Keyboard::focus_out_window (GdkEventFocus * ev, Gtk::Window* win)
+{
+       if (ev) {
+               state.clear ();
+               current_window = 0;
+       }  else {
+               current_window = 0;
+       }
+
+       DEBUG_TRACE (DEBUG::Keyboard, string_compose ("Foucusing out window, title = %1\n", win->get_title()));
+
+       return false;
+}
+
 void
 Keyboard::set_edit_button (guint but)
 {