Window focus handling fixes.

Many windows were not getting key events.
Use magic focus infrastructure (built for widgets) to deliver key events
via window focus in/out.
This commit is contained in:
nick_m 2015-04-02 02:41:49 +11:00
parent 9a4827374c
commit 35f69656e8
11 changed files with 91 additions and 52 deletions

View file

@ -64,31 +64,37 @@ ArdourDialog::~ArdourDialog ()
} }
bool bool
ArdourDialog::on_key_press_event (GdkEventKey* ev) ArdourDialog::on_focus_in_event (GdkEventFocus *ev)
{ {
if (!relay_key_press (ev, this)) { if (Keyboard::some_magic_widget_has_focus()) {
return Gtk::Window::on_key_press_event(ev); Keyboard::magic_widget_drop_focus ();
} }
return true;
Keyboard::the_keyboard().focus_in_window (ev, this);
Keyboard::magic_widget_grab_focus ();
return Dialog::on_focus_in_event (ev);
} }
bool bool
ArdourDialog::on_enter_notify_event (GdkEventCrossing *ev) ArdourDialog::on_focus_out_event (GdkEventFocus *ev)
{ {
Keyboard::the_keyboard().enter_window (ev, this); if (!get_modal()) {
return Dialog::on_enter_notify_event (ev); Keyboard::magic_widget_drop_focus ();
Keyboard::the_keyboard().focus_out_window (ev, this);
} }
return Dialog::on_focus_out_event (ev);
bool
ArdourDialog::on_leave_notify_event (GdkEventCrossing *ev)
{
Keyboard::the_keyboard().leave_window (ev, this);
return Dialog::on_leave_notify_event (ev);
} }
void void
ArdourDialog::on_unmap () 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); Keyboard::the_keyboard().leave_window (0, this);
Dialog::on_unmap (); Dialog::on_unmap ();
} }
@ -119,7 +125,7 @@ void
ArdourDialog::init () ArdourDialog::init ()
{ {
set_border_width (10); set_border_width (10);
add_events (Gdk::FOCUS_CHANGE_MASK);
set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG); set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
Gtk::Window* parent = WM::Manager::instance().transient_parent(); Gtk::Window* parent = WM::Manager::instance().transient_parent();

View 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 (Gtk::Window& parent, std::string title, bool modal = false, bool use_separator = false);
~ArdourDialog(); ~ArdourDialog();
bool on_enter_notify_event (GdkEventCrossing*); bool on_focus_in_event (GdkEventFocus*);
bool on_leave_notify_event (GdkEventCrossing*); bool on_focus_out_event (GdkEventFocus*);
bool on_delete_event (GdkEventAny*); bool on_delete_event (GdkEventAny*);
bool on_key_press_event (GdkEventKey*);
void on_unmap (); void on_unmap ();
void on_show (); void on_show ();

View file

@ -2623,10 +2623,8 @@ ARDOUR_UI::edit_metadata ()
{ {
SessionMetadataEditor dialog; SessionMetadataEditor dialog;
dialog.set_session (_session); dialog.set_session (_session);
Keyboard::magic_widget_grab_focus ();
dialog.grab_focus (); dialog.grab_focus ();
dialog.run (); dialog.run ();
Keyboard::magic_widget_drop_focus ();
} }
void void

View file

@ -58,26 +58,48 @@ ArdourWindow::~ArdourWindow ()
bool bool
ArdourWindow::on_key_press_event (GdkEventKey* ev) 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 bool
ArdourWindow::on_enter_notify_event (GdkEventCrossing *ev) ArdourWindow::on_focus_in_event (GdkEventFocus *ev)
{ {
Keyboard::the_keyboard().enter_window (ev, this); if (Keyboard::some_magic_widget_has_focus()) {
return Window::on_enter_notify_event (ev); 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 bool
ArdourWindow::on_leave_notify_event (GdkEventCrossing *ev) ArdourWindow::on_focus_out_event (GdkEventFocus *ev)
{ {
Keyboard::the_keyboard().leave_window (ev, this); if (!get_modal()) {
return Window::on_leave_notify_event (ev); Keyboard::magic_widget_drop_focus ();
Keyboard::the_keyboard().focus_out_window (ev, this);
}
return Window::on_focus_out_event (ev);
} }
void void
ArdourWindow::on_unmap () 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); Keyboard::the_keyboard().leave_window (0, this);
Window::on_unmap (); Window::on_unmap ();
} }
@ -92,6 +114,7 @@ void
ArdourWindow::init () ArdourWindow::init ()
{ {
set_border_width (10); 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 they should be considered part of the same "window level" as a dialog. This

View file

@ -44,8 +44,8 @@ class ArdourWindow : public Gtk::Window, public ARDOUR::SessionHandlePtr, public
ArdourWindow (Gtk::Window& parent, std::string title); ArdourWindow (Gtk::Window& parent, std::string title);
~ArdourWindow(); ~ArdourWindow();
bool on_enter_notify_event (GdkEventCrossing*); bool on_focus_in_event (GdkEventFocus*);
bool on_leave_notify_event (GdkEventCrossing*); bool on_focus_out_event (GdkEventFocus*);
bool on_delete_event (GdkEventAny *); bool on_delete_event (GdkEventAny *);
bool on_key_press_event (GdkEventKey*); bool on_key_press_event (GdkEventKey*);
void on_unmap (); void on_unmap ();

View file

@ -536,22 +536,6 @@ ExportVideoDialog::on_show ()
Dialog::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 void
ExportVideoDialog::abort_clicked () ExportVideoDialog::abort_clicked ()
{ {

View file

@ -64,9 +64,6 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList
void set_original_file_information (); void set_original_file_information ();
bool on_focus_in_event (GdkEventFocus*);
bool on_focus_out_event (GdkEventFocus*);
void open_outfn_dialog (); void open_outfn_dialog ();
void open_invid_dialog (); void open_invid_dialog ();
void scale_checkbox_toggled (); void scale_checkbox_toggled ();

View file

@ -184,7 +184,7 @@ KeyEditor::on_key_press_event (GdkEventKey* ev)
if (!ev->is_modifier) { if (!ev->is_modifier) {
last_keyval = ev->keyval; last_keyval = ev->keyval;
} }
return false; return ArdourWindow::on_key_press_event (ev);
} }
bool bool

View file

@ -357,7 +357,10 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
if (_pluginui->non_gtk_gui()) { if (_pluginui->non_gtk_gui()) {
_pluginui->forward_key_event (event); _pluginui->forward_key_event (event);
} else { } else {
return relay_key_press (event, this); if (!relay_key_press (event, this)) {
return Window::on_key_press_event (event);
}
return true;
} }
} }
return true; return true;
@ -376,7 +379,10 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event)
*/ */
return relay_key_press (event, &PublicEditor::instance()); return relay_key_press (event, &PublicEditor::instance());
} else { } else {
return relay_key_press (event, this); if (!relay_key_press (event, this)) {
return Window::on_key_press_event (event);
}
return true;
} }
} else { } else {
return false; return false;

View file

@ -106,6 +106,8 @@ class LIBGTKMM2EXT_API Keyboard : public sigc::trackable, PBD::Stateful
bool leave_window (GdkEventCrossing *ev, Gtk::Window*); bool leave_window (GdkEventCrossing *ev, Gtk::Window*);
bool enter_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_contains (guint state, ModifierMask);
static bool modifier_state_equals (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 bool some_magic_widget_has_focus ();
static void magic_widget_grab_focus (); static void magic_widget_grab_focus ();
static void magic_widget_drop_focus (); static void magic_widget_drop_focus ();
static Gtk::Window* get_current_window () { return current_window; };
static void close_current_dialog (); static void close_current_dialog ();

View file

@ -384,6 +384,29 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* /*win*/)
return false; 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 void
Keyboard::set_edit_button (guint but) Keyboard::set_edit_button (guint but)
{ {