use X_() to mark binding names as non-translated
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 997b790c1a5fe4a1e84e90ec6232c70df09a6063..9f886ed5125e5047804768bc5fa4847f37a887e3 100644 (file)
@@ -111,7 +111,6 @@ typedef uint64_t microseconds_t;
 #include "audio_clock.h"
 #include "audio_region_view.h"
 #include "big_clock_window.h"
-#include "binding_owners.h"
 #include "bundle_manager.h"
 #include "duplicate_routes_dialog.h"
 #include "debug.h"
@@ -270,7 +269,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , meterbridge (0)
        , rc_option_editor (0)
        , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
-       , key_editor (X_("key-editor"), _("Key Bindings"))
        , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
        , about (X_("about"), _("About"))
        , location_ui (X_("locations"), _("Locations"))
@@ -278,11 +276,12 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
        , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
        , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
-       , add_video_dialog (X_("add-video"), _("Add Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
+       , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
        , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
        , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
        , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
        , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
+       , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this))
        , video_server_process (0)
        , splash (0)
        , have_configure_timeout (false)
@@ -860,6 +859,13 @@ ARDOUR_UI::check_announcements ()
 #endif
 }
 
+static bool
+_hide_splash (gpointer arg)
+{
+       ((ARDOUR_UI*)arg)->hide_splash();
+       return false;
+}
+
 int
 ARDOUR_UI::starting ()
 {
@@ -1032,8 +1038,6 @@ ARDOUR_UI::starting ()
 
        use_config ();
 
-       goto_editor_window ();
-
        WM::Manager::instance().show_visible ();
 
        /* We have to do this here since goto_editor_window() ends up calling show_all() on the
@@ -1042,6 +1046,14 @@ ARDOUR_UI::starting ()
        _status_bar_visibility.update ();
 
        BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
+
+       if (splash && splash->is_visible()) {
+               // in 1 second, hide the splash screen
+               Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+       }
+
+       /* all other dialogs are created conditionally */
+
        return 0;
 }
 
@@ -3171,8 +3183,6 @@ ARDOUR_UI::close_session()
        if (get_session_parameters (true, false)) {
                exit (1);
        }
-
-       goto_editor_window ();
 }
 
 /** @param snap_name Snapshot name (without .ardour suffix).
@@ -3309,8 +3319,6 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 
        session_loaded = true;
 
-       goto_editor_window ();
-
        if (_session) {
                _session->set_clean ();
        }
@@ -4297,6 +4305,30 @@ ARDOUR_UI::mixer_settings () const
        return node;
 }
 
+XMLNode*
+ARDOUR_UI::main_window_settings () const
+{
+       XMLNode* node = 0;
+
+       if (_session) {
+               node = _session->instant_xml(X_("Main"));
+       } else {
+               node = Config->instant_xml(X_("Main"));
+       }
+
+       if (!node) {
+               if (getenv("ARDOUR_INSTANT_XML_PATH")) {
+                       node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
+               }
+       }
+
+       if (!node) {
+               node = new XMLNode (X_("Main"));
+       }
+
+       return node;
+}
+
 XMLNode*
 ARDOUR_UI::editor_settings () const
 {
@@ -5100,6 +5132,10 @@ ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void*
        window.set_flags (CAN_FOCUS);
        window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
 
+       /* This is a hack to ensure that GTK-accelerators continue to
+        * work. Once we switch over to entirely native bindings, this will be
+        * unnecessary and should be removed
+        */
        window.add_accel_group (ActionManager::ui_manager->get_accel_group());
 
        window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
@@ -5132,29 +5168,30 @@ ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
 
                /* see if it uses the ardour binding system */
 
-               HasBindings* bindable;
-               
-               if ((bindable = dynamic_cast<HasBindings*> (w)) != 0) {
-                       KeyboardKey k (ev->state, ev->keyval);
-                       bindings = &bindable->bindings();
+               if (w) {
+                       bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
+               } else {
+                       bindings = &global_bindings;
                }
 
-       } else if (window != 0) {
+               DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
+               
+       } else if (event_window != 0) {
 
                window = event_window;
                
                /* see if window uses ardour binding system */
-               
-               
-       } else {
 
-               window = &_main_window;
+               bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
                
-               /* no window supplied, try our own bindings */
+       } 
 
-               bindings = &_global_bindings;
+       /* An empty binding set is treated as if it doesn't exist */
+       
+       if (bindings && bindings->empty()) {
+               bindings = 0;
        }
-
+       
        return key_press_focus_accelerator_handler (*window, ev, bindings);
 }
                        
@@ -5164,39 +5201,34 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
        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);
+
+       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 (focus) {
+               
+               /* some widget has keyboard focus */
+
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
+
+                       /* A particular kind of focusable widget currently has keyboard
+                        * focus. All unmodified key events should go to that widget
+                        * first and not be used as an accelerator by default 
+                        */
+
                        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",
+        DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7\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")));
 
@@ -5231,85 +5263,84 @@ ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey
           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");
+               DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
+               KeyboardKey k (ev->state, ev->keyval);
+
+               if (bindings) {
+
+                       DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
+                       
+                       if (bindings->activate (k, Bindings::Press)) {
+                               DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
                                return true;
                        }
-               } else {
-                       DEBUG_TRACE (DEBUG::Accelerators, "\tactivation skipped\n");
+               }
+
+               DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+               
+               if (global_bindings.activate (k, Bindings::Press)) {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
+                       return true;
                }
 
                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
+                
+                if (gtk_window_propagate_key_event (win, ev)) {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
+                       return true;
+                }
 
-               return gtk_window_propagate_key_event (win, ev);
-       }
+       } else {
+               
+               /* no modifiers, propagate first */
+               
+               DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
+               
+               if (gtk_window_propagate_key_event (win, ev)) {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
+                       return true;
+               }
 
-       /* no modifiers, propagate first */
+               DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
+               KeyboardKey k (ev->state, ev->keyval);          
 
-        DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
+               if (bindings) {
+                       
+                       DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\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");
+                       
+                       if (bindings->activate (k, Bindings::Press)) {
+                               DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
+                               return true;
+                       }
+                       
+               } 
+               
+               DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+               
+               if (global_bindings.activate (k, Bindings::Press)) {
+                       DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
+                       return true;
                }
-
-       } else {
-                DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
-               return true;
        }
 
-        DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
+       DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
        return true;
 }
+
+void
+ARDOUR_UI::load_bindings ()
+{
+       global_bindings.set_action_map (global_actions);
+       global_bindings.load (X_("global"));
+}
+