diff options
-rw-r--r-- | gtk2_ardour/ardour_ui.cc | 221 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui.h | 6 | ||||
-rw-r--r-- | gtk2_ardour/ardour_ui2.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/binding_owners.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 15 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/utils.cc | 166 | ||||
-rw-r--r-- | gtk2_ardour/utils.h | 1 |
8 files changed, 191 insertions, 225 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 96b05dc94f..18bd872133 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -114,6 +114,7 @@ typedef uint64_t microseconds_t; #include "binding_owners.h" #include "bundle_manager.h" #include "duplicate_routes_dialog.h" +#include "debug.h" #include "engine_dialog.h" #include "export_video_dialog.h" #include "export_video_infobox.h" @@ -5087,13 +5088,19 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* } Gtkmm2ext::WindowTitle title (Glib::get_application_name()); - title += name; + + if (!name.empty()) { + title += name; + } + window.set_title (title.get_string()); window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME); window.set_flags (CAN_FOCUS); window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); + window.add_accel_group (ActionManager::ui_manager->get_accel_group()); + window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler)); window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner)); window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false); @@ -5101,22 +5108,23 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* } bool -ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* window) +ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window) { - switch (ev->type) { - case GDK_KEY_PRESS: - return key_press_handler (ev, window); - default: - break; - } + Gtkmm2ext::Bindings* bindings = 0; + Gtk::Window* window = 0; - return key_release_handler (ev, window); -} - -bool -ARDOUR_UI::key_press_handler (GdkEventKey* ev, Gtk::Window* event_window) -{ + /* until we get ardour bindings working, we are not handling key + * releases yet. + */ + + if (ev->type != GDK_KEY_PRESS) { + return false; + } + if (event_window == &_main_window) { + + window = event_window; + /* find current tab contents */ Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); @@ -5127,43 +5135,180 @@ ARDOUR_UI::key_press_handler (GdkEventKey* ev, Gtk::Window* event_window) if ((bindable = dynamic_cast<HasBindings*> (w)) != 0) { KeyboardKey k (ev->state, ev->keyval); - return bindable->bindings().activate (k, Bindings::Press); - } else { - /* no bindings in current tab, use baroque GTK mechanism */ - return key_press_focus_accelerator_handler (_main_window, ev); + bindings = &bindable->bindings(); } + } else if (window != 0) { + + window = event_window; + + /* see if window uses ardour binding system */ + + } else { + + window = &_main_window; + /* no window supplied, try our own bindings */ - KeyboardKey k (ev->state, ev->keyval); - return _global_bindings.activate (k, Bindings::Press); + + bindings = &_global_bindings; } -} + return key_press_focus_accelerator_handler (*window, ev, bindings); +} + bool -ARDOUR_UI::key_release_handler (GdkEventKey* ev, Gtk::Window* event_window) -{ - if (event_window == &_main_window) { - /* find current tab contents */ +ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings) +{ + GtkWindow* win = window.gobj(); + GtkWidget* focus = gtk_window_get_focus (win); + bool special_handling_of_unmodified_accelerators = false; + bool allow_activating = true; + /* consider all relevant modifiers but not LOCK or SHIFT */ + const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); + GdkModifierType modifier = GdkModifierType (ev->state); + modifier = GdkModifierType (modifier & gtk_accelerator_get_default_mod_mask()); + Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator(modifier); + + if (focus) { + if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) { + special_handling_of_unmodified_accelerators = true; + } + } - Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); +#ifdef GTKOSX + /* at one time this appeared to be necessary. As of July 2012, it does not + appear to be. if it ever is necessar, figure out if it should apply + to all platforms. + */ +#if 0 + if (Keyboard::some_magic_widget_has_focus ()) { + allow_activating = false; + } +#endif +#endif - /* see if it uses the ardour binding system */ - HasBindings* bindable; - - if ((bindable = dynamic_cast<HasBindings*> (w)) != 0) { - KeyboardKey k (ev->state, ev->keyval); - return bindable->bindings().activate (k, Bindings::Release); + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n", + win, + ev->keyval, + show_gdk_event_state (ev->state), + special_handling_of_unmodified_accelerators, + Keyboard::some_magic_widget_has_focus(), + allow_activating, + focus, + (focus ? gtk_widget_get_name (focus) : "no focus widget"))); + + /* This exists to allow us to override the way GTK handles + key events. The normal sequence is: + + a) event is delivered to a GtkWindow + b) accelerators/mnemonics are activated + c) if (b) didn't handle the event, propagate to + the focus widget and/or focus chain + + The problem with this is that if the accelerators include + keys without modifiers, such as the space bar or the + letter "e", then pressing the key while typing into + a text entry widget results in the accelerator being + activated, instead of the desired letter appearing + in the text entry. + + There is no good way of fixing this, but this + represents a compromise. The idea is that + key events involving modifiers (not Shift) + get routed into the activation pathway first, then + get propagated to the focus widget if necessary. + + If the key event doesn't involve modifiers, + we deliver to the focus widget first, thus allowing + it to get "normal text" without interference + from acceleration. + + Of course, this can also be problematic: if there + is a widget with focus, then it will swallow + all "normal text" accelerators. + */ + + if (!special_handling_of_unmodified_accelerators) { + + + /* XXX note that for a brief moment, the conditional above + * included "|| (ev->state & mask)" so as to enforce the + * implication of special_handling_of_UNMODIFIED_accelerators. + * however, this forces any key that GTK doesn't allow and that + * we have an alternative (see next comment) for to be + * automatically sent through the accel groups activation + * pathway, which prevents individual widgets & canvas items + * from ever seeing it if is used by a key binding. + * + * specifically, this hid Ctrl-down-arrow from MIDI region + * views because it is also bound to an action. + * + * until we have a robust, clean binding system, this + * quirk will have to remain in place. + */ + + /* pretend that certain key events that GTK does not allow + to be used as accelerators are actually something that + it does allow. but only where there are no modifiers. + */ + + uint32_t fakekey = ev->keyval; + + if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) { + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tactivate (was %1 now %2) without special hanlding of unmodified accels\n", + ev->keyval, fakekey)); + + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tmodified modifier was %1\n", show_gdk_event_state (modifier))); + + if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, modifier)) { + DEBUG_TRACE (DEBUG::Accelerators, "\taccel group activated by fakekey\n"); + return true; + } + } + } + + if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) { + + /* no special handling or there are modifiers in effect: accelerate first */ + + DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n"); + DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n", + ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval))); + + if (allow_activating) { + DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n"); + if (gtk_accel_groups_activate (G_OBJECT(win), ev->keyval, modifier)) { + DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); + return true; + } + } else { + DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n"); + } + + DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n"); + + return gtk_window_propagate_key_event (win, ev); + } + + /* no modifiers, propagate first */ + + DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n"); + + if (!gtk_window_propagate_key_event (win, ev)) { + DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n"); + if (allow_activating) { + return gtk_accel_groups_activate (G_OBJECT(win), ev->keyval, modifier); } else { - /* no bindings in current tab, use baroque GTK mechanism */ - return key_press_focus_accelerator_handler (_main_window, ev); + DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n"); } } else { - /* no window supplied, try our own bindings */ - KeyboardKey k (ev->state, ev->keyval); - return _global_bindings.activate (k, Bindings::Release); ->>>>>>> first compilable version of tabbable design. + DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n"); + return true; } + + DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n"); + return true; } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index cb2c6ade90..e2db285148 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -336,9 +336,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr gpointer user_data); bool tabbed_window_state_event_handler (GdkEventWindowState*, void* object); - - bool key_press_handler (GdkEventKey*, Gtk::Window* event_window); - bool key_release_handler (GdkEventKey*, Gtk::Window* event_window); + bool key_event_handler (GdkEventKey*, Gtk::Window* window); protected: friend class PublicEditor; @@ -827,7 +825,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void grab_focus_after_dialog (); void tabs_switch (GtkNotebookPage*, guint page_number); - bool key_event_handler (GdkEventKey*, Gtk::Window* window); + bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings*); }; #endif /* __ardour_gui_h__ */ diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index 07528c76c5..efd45ffaa8 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -120,7 +120,7 @@ ARDOUR_UI::setup_windows () top_packer.pack_start (menu_bar_base, false, false); #endif - main_vpacker.pack_start (top_packer); + main_vpacker.pack_start (top_packer, false, false); /* now add the transport frame to the top of main window */ diff --git a/gtk2_ardour/binding_owners.h b/gtk2_ardour/binding_owners.h index d896afb977..a815cc72af 100644 --- a/gtk2_ardour/binding_owners.h +++ b/gtk2_ardour/binding_owners.h @@ -28,7 +28,7 @@ class HasBindings { public: HasBindings (Gtkmm2ext::Bindings& b) : _bindings (b) {} - Gtkmm2ext::Bindings bindings() const { return _bindings; } + Gtkmm2ext::Bindings& bindings() const { return _bindings; } protected: Gtkmm2ext::Bindings& _bindings; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index d6ad614043..aed4330c46 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -4286,20 +4286,6 @@ Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/) atv.clear_playlist (); } -bool -Editor::on_key_press_event (GdkEventKey* ev) -{ - return key_press_focus_accelerator_handler (*current_toplevel(), ev); -} - -bool -Editor::on_key_release_event (GdkEventKey* ev) -{ - return false; - // return Gtk::Window::on_key_release_event (ev); - // return key_press_focus_accelerator_handler (*this, ev); -} - double Editor::get_y_origin () const { @@ -5957,7 +5943,6 @@ Editor::use_own_window () if (win && new_window) { win->set_name ("EditorWindow"); - win->add_accel_group (ActionManager::ui_manager->get_accel_group()); ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 5e25936050..8f00fe110b 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2099,9 +2099,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void toggle_gain_envelope_active (); void reset_region_gain_envelopes (); - bool on_key_press_event (GdkEventKey*); - bool on_key_release_event (GdkEventKey*); - void session_state_saved (std::string); Glib::RefPtr<Gtk::Action> undo_action; diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 3c7945993a..557804948c 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -297,12 +297,7 @@ ARDOUR_UI_UTILS::gdk_color_to_rgba (Gdk::Color const& c) bool ARDOUR_UI_UTILS::relay_key_press (GdkEventKey* ev, Gtk::Window* win) { - switch (ev->type) { - case GDK_KEY_PRESS: - return ARDOUR_UI::instance()->key_press_handler (ev, win); - default: - return ARDOUR_UI::instance()->key_release_handler (ev, win); - } + return ARDOUR_UI::instance()->key_event_handler (ev, win); } bool @@ -334,8 +329,8 @@ ARDOUR_UI_UTILS::emulate_key_event (unsigned int keyval) return relay_key_press(&ev); } -static string -show_gdk_event_state (int state) +string +ARDOUR_UI_UTILS::show_gdk_event_state (int state) { string s; if (state & GDK_SHIFT_MASK) { @@ -392,161 +387,6 @@ show_gdk_event_state (int state) return s; } -bool -ARDOUR_UI_UTILS::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) -{ - GtkWindow* win = window.gobj(); - GtkWidget* focus = gtk_window_get_focus (win); - bool special_handling_of_unmodified_accelerators = false; - bool allow_activating = true; - /* consider all relevant modifiers but not LOCK or SHIFT */ - const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); - GdkModifierType modifier = GdkModifierType (ev->state); - modifier = GdkModifierType (modifier & gtk_accelerator_get_default_mod_mask()); - Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator(modifier); - - if (focus) { - if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) { - special_handling_of_unmodified_accelerators = true; - } - } - -#ifdef GTKOSX - /* at one time this appeared to be necessary. As of July 2012, it does not - appear to be. if it ever is necessar, figure out if it should apply - to all platforms. - */ -#if 0 - if (Keyboard::some_magic_widget_has_focus ()) { - allow_activating = false; - } -#endif -#endif - - - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n", - win, - ev->keyval, - show_gdk_event_state (ev->state), - special_handling_of_unmodified_accelerators, - Keyboard::some_magic_widget_has_focus(), - allow_activating, - focus, - (focus ? gtk_widget_get_name (focus) : "no focus widget"))); - - /* This exists to allow us to override the way GTK handles - key events. The normal sequence is: - - a) event is delivered to a GtkWindow - b) accelerators/mnemonics are activated - c) if (b) didn't handle the event, propagate to - the focus widget and/or focus chain - - The problem with this is that if the accelerators include - keys without modifiers, such as the space bar or the - letter "e", then pressing the key while typing into - a text entry widget results in the accelerator being - activated, instead of the desired letter appearing - in the text entry. - - There is no good way of fixing this, but this - represents a compromise. The idea is that - key events involving modifiers (not Shift) - get routed into the activation pathway first, then - get propagated to the focus widget if necessary. - - If the key event doesn't involve modifiers, - we deliver to the focus widget first, thus allowing - it to get "normal text" without interference - from acceleration. - - Of course, this can also be problematic: if there - is a widget with focus, then it will swallow - all "normal text" accelerators. - */ - - if (!special_handling_of_unmodified_accelerators) { - - - /* XXX note that for a brief moment, the conditional above - * included "|| (ev->state & mask)" so as to enforce the - * implication of special_handling_of_UNMODIFIED_accelerators. - * however, this forces any key that GTK doesn't allow and that - * we have an alternative (see next comment) for to be - * automatically sent through the accel groups activation - * pathway, which prevents individual widgets & canvas items - * from ever seeing it if is used by a key binding. - * - * specifically, this hid Ctrl-down-arrow from MIDI region - * views because it is also bound to an action. - * - * until we have a robust, clean binding system, this - * quirk will have to remain in place. - */ - - /* pretend that certain key events that GTK does not allow - to be used as accelerators are actually something that - it does allow. but only where there are no modifiers. - */ - - uint32_t fakekey = ev->keyval; - - if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) { - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tactivate (was %1 now %2) without special hanlding of unmodified accels\n", - ev->keyval, fakekey)); - - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tmodified modifier was %1\n", show_gdk_event_state (modifier))); - - if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, modifier)) { - DEBUG_TRACE (DEBUG::Accelerators, "\taccel group activated by fakekey\n"); - return true; - } - } - } - - if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) { - - /* no special handling or there are modifiers in effect: accelerate first */ - - DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n"); - DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n", - ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval))); - - if (allow_activating) { - DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n"); - if (gtk_accel_groups_activate (G_OBJECT(win), ev->keyval, modifier)) { - DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n"); - return true; - } - } else { - DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n"); - } - - DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n"); - - return gtk_window_propagate_key_event (win, ev); - } - - /* no modifiers, propagate first */ - - DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n"); - - if (!gtk_window_propagate_key_event (win, ev)) { - DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n"); - if (allow_activating) { - return gtk_accel_groups_activate (G_OBJECT(win), ev->keyval, modifier); - } else { - DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n"); - } - - } else { - DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n"); - return true; - } - - DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n"); - return true; -} Glib::RefPtr<Gdk::Pixbuf> ARDOUR_UI_UTILS::get_xpm (std::string name) diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h index d883e74fa5..1c30172685 100644 --- a/gtk2_ardour/utils.h +++ b/gtk2_ardour/utils.h @@ -92,6 +92,7 @@ std::string rate_as_string (float r); bool windows_overlap (Gtk::Window *a, Gtk::Window *b); bool overwrite_file_dialog (Gtk::Window& parent, std::string title, std::string text); +std::string show_gdk_event_state (int state); } // namespace #endif /* __ardour_gtk_utils_h__ */ |