diff --git a/gtk2_ardour/ardour.keys.in b/gtk2_ardour/ardour.keys.in index bdb40eb04d..54f539925e 100644 --- a/gtk2_ardour/ardour.keys.in +++ b/gtk2_ardour/ardour.keys.in @@ -228,6 +228,7 @@ This mode provides many different operations on both regions and control points, @sess|Main/AddTrackBus|<@PRIMARY@><@TERTIARY@>n|add track(s) or bus(ses) @sess|Main/New|<@PRIMARY@>n|open a new session @wvis|Window/toggle-midi-connection-manager|<@SECONDARY@><@TERTIARY@>m|toggle global midi patchbay +@wvis|Common/toggle-editor-and-mixer|<@SECONDARY@>m|toggle editor & mixer ;; arrow keys, navigation etc. diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 2636bc015d..ab8561acd6 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -376,8 +376,10 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void hide_tabbable (Gtkmm2ext::Tabbable*); void detach_tabbable (Gtkmm2ext::Tabbable*); void attach_tabbable (Gtkmm2ext::Tabbable*); - void change_tabbable_visibility (Gtkmm2ext::Tabbable*); - + void button_change_tabbable_visibility (Gtkmm2ext::Tabbable*); + void key_change_tabbable_visibility (Gtkmm2ext::Tabbable*); + void toggle_editor_and_mixer (); + void tabbable_state_change (Gtkmm2ext::Tabbable&); void toggle_meterbridge (); diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc index e4e649e459..939c7d0eeb 100644 --- a/gtk2_ardour/ardour_ui_dependents.cc +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -87,11 +87,13 @@ ARDOUR_UI::we_have_dependents () editor->setup_tooltips (); editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks)); - /* catch up on tabbable state */ + /* catch up on tabbable state, in the right order to leave the editor + * selected by default + */ - tabbable_state_change (*editor); - tabbable_state_change (*mixer); tabbable_state_change (*rc_option_editor); + tabbable_state_change (*mixer); + tabbable_state_change (*editor); /* all actions are defined */ diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 869bda877b..51eabfa849 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -329,13 +329,90 @@ ARDOUR_UI::unload_session (bool hide_stuff) } void -ARDOUR_UI::change_tabbable_visibility (Tabbable* t) +ARDOUR_UI::toggle_editor_and_mixer () +{ + if (editor->tabbed() && mixer->tabbed()) { + if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) { + _tabs.set_current_page (_tabs.page_num (mixer->contents())); + } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) { + _tabs.set_current_page (_tabs.page_num (editor->contents())); + } else { + /* do nothing */ + } + return; + } + + if (editor->tabbed() && !mixer->tabbed()) { + if (!editor->fully_visible()) { + if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) { + mixer->make_visible (); + } + } else { + _main_window.present (); + } + return; + } + + if (mixer->tabbed () && !editor->tabbed()) { + if (!editor->fully_visible()) { + if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) { + editor->make_visible (); + } + } else { + _main_window.present (); + } + return; + } + + if (editor->fully_visible()) { + mixer->make_visible (); + } else { + editor->make_visible (); + } +} + +void +ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t) { if (!t) { return; } - t->change_visibility(); + if (t->tabbed()) { + _tabs.set_current_page (_tabs.page_num (t->contents())); + } else if (!t->fully_visible()) { + t->make_visible (); + } else { + _main_window.present (); + } +} + +void +ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t) +{ + /* For many/most users, clicking a button in the main window will make it + the main/front/key window, which will change any stacking relationship they + were trying to modify by clicking on the button in the first + place. This button-aware method knows that click on + a button designed to show/hide a Tabbable that has its own window + will have made that window be obscured (as the main window comes to + the front). We therefore *hide* the Tabbable's window if it is even + partially visible, believing that this is likely because the + Tabbable window used to be front, the user clicked to change that, + and before we even get here, the main window has become front. + */ + + if (!t) { + return; + } + + if (t->tabbed()) { + _tabs.set_current_page (_tabs.page_num (t->contents())); + } else if (t->visible()) { + t->hide(); + } else { + t->make_visible (); + } } void @@ -554,6 +631,10 @@ ARDOUR_UI::tabbable_state_change (Tabbable& t) vis_button->set_active_state (Gtkmm2ext::Off); break; } + + for (std::vector::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) { + (*b)->set_active_state (Gtkmm2ext::Off); + } } void diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index da88fab6b1..9fdde7219f 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -242,9 +242,19 @@ ARDOUR_UI::install_actions () are for the tab/window control buttons, which have somewhat odd semantics. */ - global_actions.register_action (common_actions, X_("change-editor-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::change_tabbable_visibility), editor)); - global_actions.register_action (common_actions, X_("change-mixer-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::change_tabbable_visibility), mixer)); - global_actions.register_action (common_actions, X_("change-preferences-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::change_tabbable_visibility), rc_option_editor)); + global_actions.register_action (common_actions, X_("change-editor-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), editor)); + global_actions.register_action (common_actions, X_("change-mixer-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), mixer)); + global_actions.register_action (common_actions, X_("change-preferences-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::button_change_tabbable_visibility), rc_option_editor)); + + /* These "change" actions are not intended to be used inside menus, but + are for the tab/window control key bindings, which have somewhat odd + semantics. + */ + global_actions.register_action (common_actions, X_("key-change-editor-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), editor)); + global_actions.register_action (common_actions, X_("key-change-mixer-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), mixer)); + global_actions.register_action (common_actions, X_("key-change-preferences-visibility"), _("Change"), sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_change_tabbable_visibility), rc_option_editor)); + + global_actions.register_action (common_actions, X_("toggle-editor-and-mixer"), _("Toggle Editor & Mixer"), sigc::mem_fun (*this, &ARDOUR_UI::toggle_editor_and_mixer)); /* windows visibility actions */ diff --git a/libs/gtkmm2ext/gtkmm2ext/window_proxy.h b/libs/gtkmm2ext/gtkmm2ext/window_proxy.h index a7923e8e04..abacca2428 100644 --- a/libs/gtkmm2ext/gtkmm2ext/window_proxy.h +++ b/libs/gtkmm2ext/gtkmm2ext/window_proxy.h @@ -52,8 +52,8 @@ class LIBGTKMM2EXT_API WindowProxy : public PBD::StatefulDestructible, public vi void present (); void maybe_show (); - bool visible() const { return _visible; } - bool not_visible() const { return !_visible; } + bool visible() const; + bool fully_visible() const; const std::string& name() const { return _name; } const std::string& menu_name() const { return _menu_name; } diff --git a/libs/gtkmm2ext/tabbable.cc b/libs/gtkmm2ext/tabbable.cc index 1c720591f5..be898a5555 100644 --- a/libs/gtkmm2ext/tabbable.cc +++ b/libs/gtkmm2ext/tabbable.cc @@ -188,11 +188,8 @@ Tabbable::change_visibility () } if (_window && (current_toplevel() == _window)) { - if (_window->is_visible ()) { - _window->hide (); - } else { - _window->present (); - } + /* Use WindowProxy method which will rotate then hide */ + toggle(); } } diff --git a/libs/gtkmm2ext/window_proxy.cc b/libs/gtkmm2ext/window_proxy.cc index 8efebd0241..b40e373046 100644 --- a/libs/gtkmm2ext/window_proxy.cc +++ b/libs/gtkmm2ext/window_proxy.cc @@ -233,6 +233,26 @@ WindowProxy::setup () set_pos_and_size (); } +bool +WindowProxy::visible() const +{ + if (vistracker) { + /* update with current state */ + _visible = vistracker->partially_visible(); + } + return _visible; +} + +bool +WindowProxy::fully_visible () const +{ + if (!vistracker) { + /* no vistracker .. no window .. cannot be fully visible */ + return false; + } + return vistracker->fully_visible(); +} + void WindowProxy::show () {