summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc221
-rw-r--r--gtk2_ardour/ardour_ui.h6
-rw-r--r--gtk2_ardour/ardour_ui2.cc2
-rw-r--r--gtk2_ardour/binding_owners.h2
-rw-r--r--gtk2_ardour/editor.cc15
-rw-r--r--gtk2_ardour/editor.h3
-rw-r--r--gtk2_ardour/utils.cc166
-rw-r--r--gtk2_ardour/utils.h1
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__ */