diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2015-07-07 22:12:21 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2016-02-22 15:31:21 -0500 |
commit | 9010262bed21611f2db652d16f63e4af4380259d (patch) | |
tree | b112724d2b26eb3b66b5e1c5571dbf6c5509cc24 /gtk2_ardour | |
parent | 85eee3b09dd53f6f5d1803f2b585270ab535e16f (diff) |
first compilable version of tabbable design.
I would have loved to split this apart, but there are just so many interrelated changes,
it makes little sense and would be a huge effort that would break future git bisect
use because so many intermediate commits would not compile
Diffstat (limited to 'gtk2_ardour')
37 files changed, 945 insertions, 1111 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 9396ffb89f..96b05dc94f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -48,6 +48,7 @@ #include "pbd/error.h" #include "pbd/basename.h" #include "pbd/compose.h" +#include "pbd/convert.h" #include "pbd/failed_constructor.h" #include "pbd/enumwriter.h" #include "pbd/memento_command.h" @@ -110,6 +111,7 @@ 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 "engine_dialog.h" @@ -224,8 +226,12 @@ libxml_structured_error_func (void* /* parsing_context*/, ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) +<<<<<<< HEAD : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp) +======= + : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp) +>>>>>>> first compilable version of tabbable design. , session_loaded (false) , gui_object_state (new GUIObjectState) , primary_clock (new MainClock (X_("primary"), X_("transport"), true )) @@ -262,13 +268,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , save_as_dialog (0) , meterbridge (0) , rc_option_editor (0) - , open_session_selector (0) - , _numpad_locate_happening (false) - , _session_is_new (false) - , last_key_press_time (0) - , save_as_dialog (0) - , 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")) @@ -414,20 +413,24 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) const XMLNode* ui_xml = Config->extra_xml (X_("UI")); if (ui_xml) { - key_editor.set_state (*ui_xml); - // rc_option_editor.set_state (*ui_xml); - session_option_editor.set_state (*ui_xml); - speaker_config_window.set_state (*ui_xml); - about.set_state (*ui_xml); - add_route_dialog.set_state (*ui_xml); - add_video_dialog.set_state (*ui_xml); - route_params.set_state (*ui_xml); - bundle_manager.set_state (*ui_xml); - location_ui.set_state (*ui_xml); - big_clock_window.set_state (*ui_xml); - audio_port_matrix.set_state (*ui_xml); - midi_port_matrix.set_state (*ui_xml); - export_video_dialog.set_state (*ui_xml); + key_editor.set_state (*ui_xml, 0); + session_option_editor.set_state (*ui_xml, 0); + speaker_config_window.set_state (*ui_xml, 0); + about.set_state (*ui_xml, 0); + add_route_dialog.set_state (*ui_xml, 0); + add_video_dialog.set_state (*ui_xml, 0); + route_params.set_state (*ui_xml, 0); + bundle_manager.set_state (*ui_xml, 0); + location_ui.set_state (*ui_xml, 0); + big_clock_window.set_state (*ui_xml, 0); + audio_port_matrix.set_state (*ui_xml, 0); + midi_port_matrix.set_state (*ui_xml, 0); + export_video_dialog.set_state (*ui_xml, 0); + + /* tabbables */ + // rc_option_editor->set_state (*ui_xml, 0); + // editor->set_state (*ui_xml, 0); + // mixer->set_state (*ui_xml, 0); } WM::Manager::instance().register_window (&key_editor); @@ -540,7 +543,7 @@ was not fast enough. Try to restart\n\ the audio backend and save the session."), PROGRAM_NAME); } - MessageDialog msg (*editor, msgstr); + MessageDialog msg (_main_window, msgstr); pop_back_splash (msg); msg.run (); @@ -1104,7 +1107,6 @@ ARDOUR_UI::check_memory_locking () pop_back_splash (msg); - editor->ensure_float (msg); msg.run (); if (cb.get_active()) { @@ -1150,7 +1152,7 @@ ARDOUR_UI::finish() /* use the default name */ if (save_state_canfail ("")) { /* failed - don't quit */ - MessageDialog msg (*editor, + MessageDialog msg (_main_window, string_compose (_("\ %1 was unable to save your session.\n\n\ If you still wish to quit, please use the\n\n\ @@ -1765,7 +1767,7 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out } catch (...) { - MessageDialog msg (*editor, + MessageDialog msg (_main_window, string_compose (_("There are insufficient ports available\n\ to create a new track or bus.\n\ You should save %1, exit and\n\ @@ -1826,7 +1828,7 @@ ARDOUR_UI::session_add_audio_route ( } catch (...) { - MessageDialog msg (*editor, + MessageDialog msg (_main_window, string_compose (_("There are insufficient ports available\n\ to create a new track or bus.\n\ You should save %1, exit and\n\ @@ -1972,7 +1974,7 @@ ARDOUR_UI::transport_record (bool roll) switch (_session->record_status()) { case Session::Disabled: if (_session->ntracks() == 0) { - MessageDialog msg (*editor, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu.")); + MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu.")); msg.run (); return; } @@ -3522,7 +3524,7 @@ ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* lis removed = rep.paths.size(); if (removed == 0) { - MessageDialog msgd (*editor, + MessageDialog msgd (_main_window, _("No files were ready for clean-up"), true, Gtk::MESSAGE_INFO, @@ -4344,7 +4346,7 @@ void ARDOUR_UI::halt_on_xrun_message () { cerr << "HALT on xrun\n"; - MessageDialog msg (*editor, _("Recording was stopped because your system could not keep up.")); + MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up.")); msg.run (); } @@ -4373,7 +4375,7 @@ ARDOUR_UI::disk_overrun_handler () if (!have_disk_speed_dialog_displayed) { have_disk_speed_dialog_displayed = true; - MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\ + MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\ The disk system on your computer\n\ was not able to keep up with %1.\n\ \n\ @@ -4508,7 +4510,7 @@ ARDOUR_UI::disk_underrun_handler () if (!have_disk_speed_dialog_displayed) { have_disk_speed_dialog_displayed = true; MessageDialog* msg = new MessageDialog ( - *editor, string_compose (_("The disk system on your computer\n\ + _main_window, string_compose (_("The disk system on your computer\n\ was not able to keep up with %1.\n\ \n\ Specifically, it failed to read data from disk\n\ @@ -4532,12 +4534,7 @@ ARDOUR_UI::session_dialog (std::string msg) MessageDialog* d; - if (editor) { - d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true); - } else { - d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true); - } - + d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true); d->show_all (); d->run (); delete d; @@ -5063,15 +5060,110 @@ ARDOUR_UI::hide_application () } void -ARDOUR_UI::cancel_solo () +ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner) { - if (_session) { - if (_session->soloing()) { - _session->set_solo (_session->get_routes(), false); - } else if (_session->listening()) { - _session->set_listen (_session->get_routes(), false); + /* icons, titles, WM stuff */ + + static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons; + + if (window_icons.empty()) { + Glib::RefPtr<Gdk::Pixbuf> icon; + if ((icon = ::get_icon ("ardour_icon_16px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_22px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_32px")) != 0) { + window_icons.push_back (icon); + } + if ((icon = ::get_icon ("ardour_icon_48px")) != 0) { + window_icons.push_back (icon); + } + } + + if (!window_icons.empty()) { + window.set_default_icon_list (window_icons); + } + + Gtkmm2ext::WindowTitle title (Glib::get_application_name()); + 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.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); + window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false); +} + +bool +ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* window) +{ + switch (ev->type) { + case GDK_KEY_PRESS: + return key_press_handler (ev, window); + default: + break; + } + + return key_release_handler (ev, window); +} + +bool +ARDOUR_UI::key_press_handler (GdkEventKey* ev, Gtk::Window* event_window) +{ + if (event_window == &_main_window) { + /* find current tab contents */ + + Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); + + /* 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::Press); + } else { + /* no bindings in current tab, use baroque GTK mechanism */ + return key_press_focus_accelerator_handler (_main_window, ev); } - _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window + } else { + /* no window supplied, try our own bindings */ + KeyboardKey k (ev->state, ev->keyval); + return _global_bindings.activate (k, Bindings::Press); + } +} + +bool +ARDOUR_UI::key_release_handler (GdkEventKey* ev, Gtk::Window* event_window) +{ + if (event_window == &_main_window) { + /* find current tab contents */ + + Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page()); + + /* 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); + } else { + /* no bindings in current tab, use baroque GTK mechanism */ + return key_press_focus_accelerator_handler (_main_window, ev); + } + + } 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. } } diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index ddec14b1a1..cb2c6ade90 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -53,10 +53,12 @@ #include <gtkmm/menubar.h> #include <gtkmm/textbuffer.h> #include <gtkmm/adjustment.h> -#include <gtkmm2ext/gtk_ui.h> -#include <gtkmm2ext/click_box.h> -#include <gtkmm2ext/stateful_button.h> -#include <gtkmm2ext/bindable_button.h> + +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/click_box.h" +#include "gtkmm2ext/stateful_button.h" +#include "gtkmm2ext/bindable_button.h" +#include "gtkmm2ext/bindings.h" #include "ardour/ardour.h" #include "ardour/types.h" @@ -321,14 +323,23 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void hide_application (); Gtk::Notebook& tabs(); + Gtk::Window& main_window () { return _main_window; } + + void setup_toplevel_window (Gtk::Window&, const std::string& name, void* owner); /* called from a static C function */ - Gtk::Notebook* tab_window_root_drop (GtkNotebook* src, - GtkWidget* w, - gint x, - gint y, - gpointer user_data); + GtkNotebook* tab_window_root_drop (GtkNotebook* src, + GtkWidget* w, + gint x, + gint y, + 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); + protected: friend class PublicEditor; @@ -349,13 +360,21 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void toggle_session_options_window (); private: - Mixer_UI* mixer; - NSM_Client* nsm; - bool _was_dirty; - bool _mixer_on_top; - bool _initial_verbose_plugin_scan; - bool first_time_engine_run; - + Gtk::Window _main_window; + Gtk::VBox main_vpacker; + Gtk::HBox status_bar_hpacker; + Gtk::Notebook _tabs; + PublicEditor* editor; + Mixer_UI* mixer; + Gtk::Tooltips _tooltips; + NSM_Client* nsm; + bool _was_dirty; + bool _mixer_on_top; + bool _initial_verbose_plugin_scan; + bool first_time_engine_run; + + Gtkmm2ext::Bindings _global_bindings; + void goto_editor_window (); void goto_mixer_window (); void toggle_mixer_window (); @@ -397,8 +416,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void start_clocking (); void stop_clocking (); - bool main_window_state_event_handler (GdkEventWindowState*, bool window_was_editor); - void update_transport_clocks (framepos_t pos); void record_state_changed (); @@ -627,17 +644,16 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr void setup_order_hint (AddRouteDialog::InsertAt); int create_mixer (); - PublicEditor *editor; int create_editor (); Meterbridge *meterbridge; int create_meterbridge (); - RCOptionEditor* rc_option_editor; - Gtk::HBox rc_option_editor_placeholder; - /* Dialogs that can be created via new<T> */ + RCOptionEditor* rc_option_editor; + Gtk::HBox rc_option_editor_placeholder; + WM::Proxy<SpeakerDialog> speaker_config_window; WM::Proxy<KeyEditor> key_editor; WM::Proxy<AddRouteDialog> add_route_dialog; @@ -811,6 +827,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); }; #endif /* __ardour_gui_h__ */ diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index 554e955dbf..07528c76c5 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -74,12 +74,7 @@ tab_window_root_drop (GtkNotebook* src, gint y, gpointer user_data) { - Gtk::Notebook* nb = ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data); - if (nb) { - return nb->gobj(); - } else { - return 0; - } + return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data); } int @@ -125,25 +120,40 @@ ARDOUR_UI::setup_windows () top_packer.pack_start (menu_bar_base, false, false); #endif - editor->add_toplevel_menu (top_packer); + main_vpacker.pack_start (top_packer); - editor->add_transport_frame (transport_frame); - editor->tabs().append_page (rc_option_editor_placeholder, _("Preferences")); + /* now add the transport frame to the top of main window */ + + main_vpacker.pack_start (transport_frame, false, false); + main_vpacker.pack_start (_tabs, true, true); - editor->tabs().signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch)); - - /* It would be nice if Gtkmm had wrapped this rather than just - * deprecating the old set_window_creation_hook() method, but oh well... - */ - g_signal_connect (editor->tabs().gobj(), "create-window", - (GCallback) ::tab_window_root_drop, this); +#ifdef TOP_MENUBAR + main_vpacker.pack_start (status_bar_hpacker, false, false); +#endif setup_transport(); - build_menu_bar (); - setup_tooltips (); + /* pack the main vpacker into the main window and show everything + */ + + _main_window.add (main_vpacker); + transport_frame.show_all (); + _main_window.show_all (); + + setup_toplevel_window (_main_window, "", this); + + rc_option_editor = new RCOptionEditor; + rc_option_editor->add_to_notebook (_tabs, _("Preferences"), 2); + + _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch)); + + /* It would be nice if Gtkmm had wrapped this rather than just + * deprecating the old set_window_creation_hook() method, but oh well... + */ + g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this); + return 0; } @@ -517,7 +527,6 @@ ARDOUR_UI::setup_transport () void ARDOUR_UI::detach_tearoff (Box* b, Widget* w) { -// editor->ensure_float (transport_tearoff->tearoff_window()); b->remove (*w); } diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc index 41af709e2f..031ebd58a8 100644 --- a/gtk2_ardour/ardour_ui_dependents.cc +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -61,8 +61,8 @@ ARDOUR_UI::we_have_dependents () editor->setup_tooltips (); editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks)); - std::cerr << "Mixer page = " << editor->tabs().append_page (*mixer, _("Mixer")) << std::endl; - editor->tabs().set_tab_detachable (*mixer); + editor->add_to_notebook (_tabs, _("Editor"), 1); + mixer->add_to_notebook (_tabs, _("Mixer"), 1); /* all actions are defined */ @@ -104,7 +104,7 @@ ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/) #endif } -Gtk::Notebook* +GtkNotebook* ARDOUR_UI::tab_window_root_drop (GtkNotebook* src, GtkWidget* w, gint x, @@ -112,20 +112,34 @@ ARDOUR_UI::tab_window_root_drop (GtkNotebook* src, gpointer) { using namespace std; + Gtk::Notebook* nb = 0; + Gtk::Window* win = 0; - if (w == GTK_WIDGET(mixer->gobj())) { + if (w == GTK_WIDGET(mixer->contents().gobj())) { /* Mixer */ - cerr << "Call use own window\n"; + cerr << "Call use own window, mixer\n"; - Gtk::Notebook* nb = mixer->use_own_window (); - Gtk::Window* win = (Gtk::Window*) nb->get_toplevel (); + nb = mixer->tab_root_drop (); + win = mixer->own_window (); + + } else if (w == GTK_WIDGET(editor->contents().gobj())) { + + /* Editor */ + + cerr << "Call use own window, editor\n"; - win->move (x, y); - win->present (); + nb = editor->tab_root_drop (); + win = editor->own_window (); - return nb; } - return 0; + if (nb) { + win->move (x, y); + win->show_all (); + win->present (); + return nb->gobj(); + } + + return 0; /* what was that? */ } diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 84959d1e51..3bfe6d4a45 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -334,11 +334,18 @@ ARDOUR_UI::goto_editor_window () Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000); } + if (!editor->window_visible()) { + /* goto tab */ + editor->show_tab (); + return; + } + editor->show_window (); editor->present (); - /* mixer should now be on top */ - if (UIConfiguration::instance().get_transients_follow_front()) { - WM::Manager::instance().set_transient_for (editor); + + /* editor should now be on top */ + if (UIConfiguration::instance()->get_transients_follow_front()) { + WM::Manager::instance().set_transient_for (editor->own_window()); } _mixer_on_top = false; } @@ -348,9 +355,9 @@ ARDOUR_UI::goto_mixer_window () { Glib::RefPtr<Gdk::Window> win; Glib::RefPtr<Gdk::Screen> screen; - - if (editor) { - win = editor->get_window (); + + if (editor && editor->own_window()) { + win = editor->own_window ()->get_window(); } if (win) { @@ -387,23 +394,28 @@ ARDOUR_UI::toggle_mixer_window () bool show = false; bool obscuring = false; - if (mixer->not_visible ()) { - show = true; + if (!mixer->window_visible() || editor->window_visible()) { + return; } - else if ( (!editor->not_visible () && ARDOUR_UI_UTILS::windows_overlap (editor, mixer)) - || (!meterbridge->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer)) - ) { + + + + if (!mixer->window_visible ()) { + show = true; + } else if ( (!editor->not_visible () && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), mixer->own_window())) + || (!meterbridge->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer->own_window())) + ) { obscuring = true; } - - if (obscuring && (editor->property_has_toplevel_focus() || meterbridge->property_has_toplevel_focus())) { + + if (obscuring && (editor->own_window()->property_has_toplevel_focus() || meterbridge->property_has_toplevel_focus())) { show = true; } if (show) { goto_mixer_window (); } else { - mixer->hide_window ((GdkEventAny*)0); + mixer->own_window()->hide (); } } @@ -417,14 +429,12 @@ ARDOUR_UI::toggle_meterbridge () if (meterbridge->not_visible ()) { show = true; - } - else if ( (!editor->not_visible() && ARDOUR_UI_UTILS::windows_overlap (editor, meterbridge)) - || (!mixer->not_visible () && ARDOUR_UI_UTILS::windows_overlap (meterbridge, mixer)) - ) { + } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) || + (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) { obscuring = true; } - if (obscuring && (editor->property_has_toplevel_focus() || mixer->property_has_toplevel_focus())) { + if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) { show = true; } @@ -442,25 +452,29 @@ ARDOUR_UI::toggle_editor_mixer () { bool obscuring = false; - if (editor && mixer) { - if (ARDOUR_UI_UTILS::windows_overlap (editor, mixer)) { + if (!mixer->window_visible() || !editor->window_visible()) { + return; + } + + if (editor && mixer && mixer->own_window()) { + if (ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), mixer->own_window())) { obscuring = true; } } - if (mixer && !mixer->not_visible() && mixer->property_has_toplevel_focus()) { + if (mixer && !mixer->not_visible() && mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()) { if (obscuring) { goto_editor_window(); } - } else if (editor && !editor->not_visible() && editor->property_has_toplevel_focus()) { + } else if (editor && editor->window_visible() && editor->own_window()->property_has_toplevel_focus()) { if (obscuring) { goto_mixer_window(); } - } else if (mixer && mixer->not_visible()) { + } else if (mixer) { if (obscuring) { goto_mixer_window (); } - } else if (editor && editor->not_visible()) { + } else if (editor) { if (obscuring) { goto_editor_window (); } @@ -535,23 +549,23 @@ ARDOUR_UI::handle_locations_change (Location *) } bool -ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor) +ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object) { - if (window_was_editor) { + if (object == editor) { if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { if (big_clock_window) { - big_clock_window->set_transient_for (*editor); + big_clock_window->set_transient_for (*editor->own_window()); } } - } else { + } else if (object == mixer) { if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) && (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) { if (big_clock_window) { - // big_clock_window->set_transient_for (*mixer); + big_clock_window->set_transient_for (*mixer->own_window()); } } } diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 1ba5f0bd5e..1a89311ec3 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -86,7 +86,6 @@ ARDOUR_UI::create_editor () } editor->Realized.connect (sigc::mem_fun (*this, &ARDOUR_UI::editor_realized)); - editor->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), true)); editor->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), editor)); return 0; @@ -730,5 +729,5 @@ ARDOUR_UI::xrun_button_release (GdkEventButton* ev) Gtk::Notebook& ARDOUR_UI::tabs() { - return editor->tabs(); + return _tabs; } diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc index f5a8bc2713..773a2ed14f 100644 --- a/gtk2_ardour/ardour_ui_mixer.cc +++ b/gtk2_ardour/ardour_ui_mixer.cc @@ -47,7 +47,6 @@ ARDOUR_UI::create_mixer () return -1; } - mixer->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), false)); mixer->signal_event().connect (sigc::bind (sigc::ptr_fun (&Gtkmm2ext::Keyboard::catch_user_event_for_pre_dialog_focus), mixer)); return 0; @@ -66,8 +65,6 @@ ARDOUR_UI::create_meterbridge () return -1; } - meterbridge->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), false)); - return 0; } diff --git a/gtk2_ardour/binding_owners.h b/gtk2_ardour/binding_owners.h new file mode 100644 index 0000000000..d896afb977 --- /dev/null +++ b/gtk2_ardour/binding_owners.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2015 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __gtk_ardour_binding_owners_h__ +#define __gtk_ardour_binding_owners_h__ + +#include <gtkmm/box.h> + +#include "gtkmm2ext/bindings.h" + +class HasBindings { + public: + HasBindings (Gtkmm2ext::Bindings& b) : _bindings (b) {} + + Gtkmm2ext::Bindings bindings() const { return _bindings; } + + protected: + Gtkmm2ext::Bindings& _bindings; +}; + +class VBoxWithBindings : public Gtk::VBox, public HasBindings +{ + public: + VBoxWithBindings (Gtkmm2ext::Bindings& b) : HasBindings (b) {} +}; + +#endif /* __gtk_ardour_binding_owners_h__ */ diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 836360b2ef..1fc58036ca 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -252,10 +252,86 @@ pane_size_watcher (Paned* pane) } Editor::Editor () - : _join_object_range_state (JOIN_OBJECT_RANGE_NONE) - + : PublicEditor (global_hpacker) + , editor_mixer_strip_width (Wide) + , constructed (false) + , _playlist_selector (0) + , no_save_visual (false) + , leftmost_frame (0) + , samples_per_pixel (2048) + , zoom_focus (ZoomFocusPlayhead) + , mouse_mode (MouseObject) + , pre_internal_snap_type (SnapToBeat) + , pre_internal_snap_mode (SnapOff) + , internal_snap_type (SnapToBeat) + , internal_snap_mode (SnapOff) + , _join_object_range_state (JOIN_OBJECT_RANGE_NONE) + , _notebook_shrunk (false) + , location_marker_color (0) + , location_range_color (0) + , location_loop_color (0) + , location_punch_color (0) + , location_cd_marker_color (0) + , entered_marker (0) + , _show_marker_lines (false) + , clicked_axisview (0) + , clicked_routeview (0) + , clicked_regionview (0) + , clicked_selection (0) + , clicked_control_point (0) + , button_release_can_deselect (true) , _mouse_changed_selection (false) - /* time display buttons */ + , region_edit_menu_split_item (0) + , region_edit_menu_split_multichannel_item (0) + , track_region_edit_playlist_menu (0) + , track_edit_playlist_submenu (0) + , track_selection_edit_playlist_submenu (0) + , _popup_region_menu_item (0) + , global_vpacker (key_bindings) + , _track_canvas (0) + , _track_canvas_viewport (0) + , within_track_canvas (false) + , _verbose_cursor (0) + , logo_item (0) + , tempo_group (0) + , meter_group (0) + , marker_group (0) + , range_marker_group (0) + , transport_marker_group (0) + , cd_marker_group (0) + , _time_markers_group (0) + , hv_scroll_group (0) + , h_scroll_group (0) + , cursor_scroll_group (0) + , no_scroll_group (0) + , _trackview_group (0) + , _drag_motion_group (0) + , _canvas_drop_zone (0) + , no_ruler_shown_update (false) + , ruler_grabbed_widget (0) + , ruler_dialog (0) + , minsec_mark_interval (0) + , minsec_mark_modulo (0) + , minsec_nmarks (0) + , timecode_mark_modulo (0) + , timecode_nmarks (0) + , _samples_ruler_interval (0) + , bbt_bars (0) + , bbt_nmarks (0) + , bbt_bar_helper_on (0) + , bbt_accent_modulo (0) + , timecode_ruler (0) + , bbt_ruler (0) + , samples_ruler (0) + , minsec_ruler (0) + , visible_timebars (0) + , editor_ruler_menu (0) + , tempo_bar (0) + , meter_bar (0) + , marker_bar (0) + , range_marker_bar (0) + , transport_marker_bar (0) + , cd_marker_bar (0) , minsec_label (_("Mins:Secs")) , bbt_label (_("Bars:Beats")) , timecode_label (_("Timecode")) @@ -267,73 +343,139 @@ Editor::Editor () , transport_mark_label (_("Loop/Punch Ranges")) , cd_mark_label (_("CD Markers")) , videotl_label (_("Video Timeline")) + , videotl_group (0) + , playhead_cursor (0) , edit_packer (4, 4, true) - - /* the values here don't matter: layout widgets - reset them as needed. - */ - , vertical_adjustment (0.0, 0.0, 10.0, 400.0) , horizontal_adjustment (0.0, 0.0, 1e16) , unused_adjustment (0.0, 0.0, 10.0, 400.0) - , controls_layout (unused_adjustment, vertical_adjustment) - - /* tool bar related */ - - , toolbar_selection_clock_table (2,3) + , _scroll_callbacks (0) + , _visible_canvas_width (0) + , _visible_canvas_height (0) + , _full_canvas_height (0) + , edit_controls_left_menu (0) + , edit_controls_right_menu (0) + , last_update_frame (0) + , cut_buffer_start (0) + , cut_buffer_length (0) + , button_bindings (0) + , last_paste_pos (0) + , paste_count (0) + , sfbrowser (0) + , current_interthread_info (0) + , analysis_window (0) + , select_new_marker (false) + , last_scrub_x (0) + , scrubbing_direction (0) + , scrub_reversals (0) + , scrub_reverse_distance (0) + , have_pending_keyboard_selection (false) + , pending_keyboard_selection_start (0) + , _snap_type (SnapToBeat) + , _snap_mode (SnapOff) + , snap_threshold (5.0) + , ignore_gui_changes (false) + , _drags (new DragManager (this)) + , lock_dialog (0) + , last_event_time { 0, 0 } + , _dragging_playhead (false) + , _dragging_edit_point (false) + , _show_measures (true) + , _follow_playhead (true) + , _stationary_playhead (false) + , _maximised (false) + , tempo_lines (0) + , global_rect_group (0) + , time_line_group (0) + , tempo_or_meter_marker_menu (0) + , marker_menu (0) + , range_marker_menu (0) + , transport_marker_menu (0) + , new_transport_marker_menu (0) + , cd_marker_menu (0) + , marker_menu_item (0) + , bbt_beat_subdivision (4) + , _visible_track_count (-1) + , toolbar_selection_clock_table (2,3) , _mouse_mode_tearoff (0) - , automation_mode_button (_("mode")) + , automation_mode_button (_("mode")) , _zoom_tearoff (0) , _tools_tearoff (0) - - , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10))) + , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10))) + , selection (new Selection (this)) + , cut_buffer (new Selection (this)) + , _selection_memento (new SelectionMemento()) + , _all_region_actions_sensitized (false) + , _ignore_region_action (false) + , _last_region_menu_was_main (false) + , _ignore_follow_edits (false) + , cd_marker_bar_drag_rect (0) + , range_bar_drag_rect (0) + , transport_bar_drag_rect (0) + , transport_bar_range_rect (0) + , transport_bar_preroll_rect (0) + , transport_bar_postroll_rect (0) + , transport_loop_range_rect (0) + , transport_punch_range_rect (0) + , transport_punchin_line (0) + , transport_punchout_line (0) + , transport_preroll_rect (0) + , transport_postroll_rect (0) + , temp_location (0) + , rubberband_rect (0) + , _route_groups (0) + , _routes (0) + , _regions (0) + , _snapshots (0) + , _locations (0) + , autoscroll_horizontal_allowed (false) + , autoscroll_vertical_allowed (false) + , autoscroll_cnt (0) + , autoscroll_widget (0) + , show_gain_after_trim (false) , selection_op_cmd_depth (0) , selection_op_history_it (0) - - /* nudge */ - - , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true)) - , meters_running(false) + , current_timefx (0) + , current_mixer_strip (0) + , show_editor_mixer_when_tracks_arrive (false) + , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true)) + , current_stepping_trackview (0) + , last_track_height_step_timestamp (0) + , entered_track (0) + , entered_regionview (0) + , clear_entered_track (false) + , _edit_point (EditAtMouse) + , meters_running (false) + , rhythm_ferret (0) + , _have_idled (false) + , resize_idle_id (-1) + , _pending_resize_amount (0) + , _pending_resize_view (0) , _pending_locate_request (false) , _pending_initial_locate (false) + , _summary (0) + , _group_tabs (0) + , _last_motion_y (0) + , layering_order_editor (0) , _last_cut_copy_source_track (0) - , _region_selection_change_updates_region_list (true) + , _cursors (0) , _following_mixer_selection (false) , _control_point_toggled_on_press (false) , _stepping_axis_view (0) , quantize_dialog (0) , _main_menu_disabler (0) { - constructed = false; - /* we are a singleton */ PublicEditor::_instance = this; _have_idled = false; - selection = new Selection (this); - cut_buffer = new Selection (this); - _selection_memento = new SelectionMemento (); selection_op_history.clear(); before.clear(); - clicked_regionview = 0; - clicked_axisview = 0; - clicked_routeview = 0; - clicked_selection = 0; - clicked_control_point = 0; - last_update_frame = 0; - last_paste_pos = 0; - paste_count = 0; - _drags = new DragManager (this); - lock_dialog = 0; - ruler_dialog = 0; - current_mixer_strip = 0; - tempo_lines = 0; - snap_type_strings = I18N (_snap_type_strings); snap_mode_strings = I18N (_snap_mode_strings); zoom_focus_strings = I18N (_zoom_focus_strings); @@ -351,78 +493,17 @@ Editor::Editor () build_snap_type_menu(); build_edit_point_menu(); - snap_threshold = 5.0; - bbt_beat_subdivision = 4; - _visible_canvas_width = 0; - _visible_canvas_height = 0; - autoscroll_horizontal_allowed = false; - autoscroll_vertical_allowed = false; - logo_item = 0; - - analysis_window = 0; + location_marker_color = ARDOUR_UI::config()->color ("location marker"); + location_range_color = ARDOUR_UI::config()->color ("location range"); + location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker"); + location_loop_color = ARDOUR_UI::config()->color ("location loop"); + location_punch_color = ARDOUR_UI::config()->color ("location punch"); - current_interthread_info = 0; - _show_measures = true; - _maximised = false; - show_gain_after_trim = false; - - have_pending_keyboard_selection = false; - _follow_playhead = true; - _stationary_playhead = false; - editor_ruler_menu = 0; - no_ruler_shown_update = false; - marker_menu = 0; - range_marker_menu = 0; - marker_menu_item = 0; - tempo_or_meter_marker_menu = 0; - transport_marker_menu = 0; - new_transport_marker_menu = 0; - editor_mixer_strip_width = Wide; - show_editor_mixer_when_tracks_arrive = false; - region_edit_menu_split_multichannel_item = 0; - region_edit_menu_split_item = 0; - temp_location = 0; - leftmost_frame = 0; - mouse_mode = MouseObject; - current_stepping_trackview = 0; - entered_track = 0; - entered_regionview = 0; - entered_marker = 0; - clear_entered_track = false; - current_timefx = 0; - playhead_cursor = 0; - button_release_can_deselect = true; - _dragging_playhead = false; - _dragging_edit_point = false; - select_new_marker = false; - rhythm_ferret = 0; - layering_order_editor = 0; - no_save_visual = false; - resize_idle_id = -1; - within_track_canvas = false; - - scrubbing_direction = 0; - - sfbrowser = 0; + timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale)); - location_marker_color = UIConfiguration::instance().color ("location marker"); - location_range_color = UIConfiguration::instance().color ("location range"); - location_cd_marker_color = UIConfiguration::instance().color ("location cd marker"); - location_loop_color = UIConfiguration::instance().color ("location loop"); - location_punch_color = UIConfiguration::instance().color ("location punch"); - - zoom_focus = ZoomFocusPlayhead; - _edit_point = EditAtMouse; - _visible_track_count = -1; - - samples_per_pixel = 2048; /* too early to use reset_zoom () */ - - timebar_height = std::max(12., ceil (15. * UIConfiguration::instance().get_ui_scale())); TimeAxisView::setup_sizes (); ArdourMarker::setup_sizes (timebar_height); - _scroll_callbacks = 0; - bbt_label.set_name ("EditorRulerLabel"); bbt_label.set_size_request (-1, (int)timebar_height); bbt_label.set_alignment (1.0, 0.5); @@ -660,20 +741,8 @@ Editor::Editor () global_vpacker.pack_start (top_hbox, false, false); global_vpacker.pack_start (*hbox, true, true); - global_hpacker.pack_start (global_vpacker, true, true); - set_name ("EditorWindow"); - add_accel_group (ActionManager::ui_manager->get_accel_group()); - - status_bar_hpacker.show (); - - _tabs.append_page (global_hpacker, _("Editor")); - _tabs.show (); - - vpacker.pack_end (status_bar_hpacker, false, false); - vpacker.pack_end (_tabs, true, true); - /* register actions now so that set_state() can find them and set toggles/checks etc */ register_actions (); @@ -684,19 +753,6 @@ Editor::Editor () setup_toolbar (); - set_zoom_focus (zoom_focus); - set_visible_track_count (_visible_track_count); - _snap_type = SnapToBeat; - set_snap_to (_snap_type); - _snap_mode = SnapOff; - set_snap_mode (_snap_mode); - set_mouse_mode (MouseObject, true); - pre_internal_snap_type = _snap_type; - pre_internal_snap_mode = _snap_mode; - internal_snap_type = _snap_type; - internal_snap_mode = _snap_mode; - set_edit_point_preference (EditAtMouse, true); - _playlist_selector = new PlaylistSelector(); _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector))); @@ -712,39 +768,6 @@ Editor::Editor () fade_context_menu.set_name ("ArdourContextMenu"); - /* icons, titles, WM stuff */ - - list<Glib::RefPtr<Gdk::Pixbuf> > window_icons; - Glib::RefPtr<Gdk::Pixbuf> icon; - - if ((icon = ::get_icon ("ardour_icon_16px")) != 0) { - window_icons.push_back (icon); - } - if ((icon = ::get_icon ("ardour_icon_22px")) != 0) { - window_icons.push_back (icon); - } - if ((icon = ::get_icon ("ardour_icon_32px")) != 0) { - window_icons.push_back (icon); - } - if ((icon = ::get_icon ("ardour_icon_48px")) != 0) { - window_icons.push_back (icon); - } - if (!window_icons.empty()) { - // set_icon_list (window_icons); - set_default_icon_list (window_icons); - } - - WindowTitle title(Glib::get_application_name()); - title += _("Editor"); - set_title (title.get_string()); - set_wmclass (X_("ardour_editor"), PROGRAM_NAME); - - add (vpacker); - add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); - - signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler)); - signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close)); - Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released)); /* allow external control surfaces/protocols to do various things */ @@ -845,21 +868,6 @@ Editor::button_settings () const return node; } -void -Editor::add_toplevel_menu (Container& cont) -{ - vpacker.pack_start (cont, false, false); - cont.show_all (); -} - -void -Editor::add_transport_frame (Container& cont) -{ - global_vpacker.pack_start (cont, false, false); - global_vpacker.reorder_child (cont, 0); - cont.show_all (); -} - bool Editor::get_smart_mode () const { @@ -930,44 +938,6 @@ Editor::set_entered_track (TimeAxisView* tav) } void -Editor::show_window () -{ - if (!is_visible ()) { - DisplaySuspender ds; - show_all (); - - /* XXX: this is a bit unfortunate; it would probably - be nicer if we could just call show () above rather - than needing the show_all () - */ - - /* re-hide stuff if necessary */ - editor_list_button_toggled (); - parameter_changed ("show-summary"); - parameter_changed ("show-group-tabs"); - parameter_changed ("show-zoom-tools"); - - /* now reset all audio_time_axis heights, because widgets might need - to be re-hidden - */ - - TimeAxisView *tv; - - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - tv = (static_cast<TimeAxisView*>(*i)); - tv->reset_height (); - } - - if (current_mixer_strip) { - current_mixer_strip->hide_things (); - current_mixer_strip->parameter_changed ("mixer-element-visibility"); - } - } - - present (); -} - -void Editor::instant_save () { if (!constructed || !ARDOUR_UI::instance()->session_loaded) { @@ -1159,14 +1129,11 @@ Editor::access_action (std::string action_group, std::string action_item) void Editor::on_realize () { - Window::on_realize (); Realized (); if (UIConfiguration::instance().get_lock_gui_after_seconds()) { start_lock_event_timing (); } - - signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler)); } void @@ -1186,7 +1153,9 @@ Editor::generic_event_handler (GdkEvent* ev) case GDK_MOTION_NOTIFY: case GDK_KEY_PRESS: case GDK_KEY_RELEASE: - gettimeofday (&last_event_time, 0); + if (contents().is_mapped()) { + gettimeofday (&last_event_time, 0); + } break; case GDK_LEAVE_NOTIFY: @@ -1283,8 +1252,12 @@ Editor::center_screen_internal (framepos_t frame, float page) void Editor::update_title () { - ENSURE_GUI_THREAD (*this, &Editor::update_title) + ENSURE_GUI_THREAD (*this, &Editor::update_title); + if (!own_window()) { + return; + } + if (_session) { bool dirty = _session->dirty(); @@ -1302,7 +1275,7 @@ Editor::update_title () WindowTitle title(session_name); title += Glib::get_application_name(); - set_title (title.get_string()); + own_window()->set_title (title.get_string()); } else { /* ::session_going_away() will have taken care of it */ } @@ -2203,55 +2176,14 @@ Editor::set_edit_point_preference (EditPoint ep, bool force) } int -Editor::set_state (const XMLNode& node, int /*version*/) +Editor::set_state (const XMLNode& node, int version) { const XMLProperty* prop; - XMLNode* geometry; - int x, y; - Gdk::Geometry g; set_id (node); - g.base_width = default_width; - g.base_height = default_height; - x = 1; - y = 1; - - if ((geometry = find_named_node (node, "geometry")) != 0) { - - XMLProperty* prop; - - if ((prop = geometry->property("x_size")) == 0) { - prop = geometry->property ("x-size"); - } - if (prop) { - g.base_width = atoi(prop->value()); - } - if ((prop = geometry->property("y_size")) == 0) { - prop = geometry->property ("y-size"); - } - if (prop) { - g.base_height = atoi(prop->value()); - } - - if ((prop = geometry->property ("x_pos")) == 0) { - prop = geometry->property ("x-pos"); - } - if (prop) { - x = atoi (prop->value()); - - } - if ((prop = geometry->property ("y_pos")) == 0) { - prop = geometry->property ("y-pos"); - } - if (prop) { - y = atoi (prop->value()); - } - } - - set_default_size (g.base_width, g.base_height); - move (x, y); - + Tabbable::set_state (node, version); + if (_session && (prop = node.property ("playhead"))) { framepos_t pos; sscanf (prop->value().c_str(), "%" PRIi64, &pos); @@ -2475,99 +2407,82 @@ Editor::set_state (const XMLNode& node, int /*version*/) XMLNode& Editor::get_state () { - XMLNode* node = new XMLNode ("Editor"); + XMLNode& node (Tabbable::get_state()); char buf[32]; id().print (buf, sizeof (buf)); - node->add_property ("id", buf); - - if (is_realized()) { - Glib::RefPtr<Gdk::Window> win = get_window(); - - int x, y, width, height; - win->get_root_origin(x, y); - win->get_size(width, height); - - XMLNode* geometry = new XMLNode ("geometry"); - - snprintf(buf, sizeof(buf), "%d", width); - geometry->add_property("x-size", string(buf)); - snprintf(buf, sizeof(buf), "%d", height); - geometry->add_property("y-size", string(buf)); - snprintf(buf, sizeof(buf), "%d", x); - geometry->add_property("x-pos", string(buf)); - snprintf(buf, sizeof(buf), "%d", y); - geometry->add_property("y-pos", string(buf)); - snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj())); - geometry->add_property("edit-horizontal-pane-pos", string(buf)); - geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0"); - snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj())); - geometry->add_property("edit-vertical-pane-pos", string(buf)); - - node->add_child_nocopy (*geometry); - } - - maybe_add_mixer_strip_width (*node); + node.add_property ("id", buf); + +#if 0 + // need to save this somehow + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj())); + geometry->add_property("edit-horizontal-pane-pos", string(buf)); + geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0"); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj())); + geometry->add_property("edit-vertical-pane-pos", string(buf)); +#endif + + maybe_add_mixer_strip_width (node); - node->add_property ("zoom-focus", enum_2_string (zoom_focus)); + node.add_property ("zoom-focus", enum_2_string (zoom_focus)); snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel); - node->add_property ("zoom", buf); - node->add_property ("snap-to", enum_2_string (_snap_type)); - node->add_property ("snap-mode", enum_2_string (_snap_mode)); - node->add_property ("internal-snap-to", enum_2_string (internal_snap_type)); - node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); - node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type)); - node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); - node->add_property ("edit-point", enum_2_string (_edit_point)); + node.add_property ("zoom", buf); + node.add_property ("snap-to", enum_2_string (_snap_type)); + node.add_property ("snap-mode", enum_2_string (_snap_mode)); + node.add_property ("internal-snap-to", enum_2_string (internal_snap_type)); + node.add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); + node.add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type)); + node.add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); + node.add_property ("edit-point", enum_2_string (_edit_point)); snprintf (buf, sizeof(buf), "%d", _visible_track_count); - node->add_property ("visible-track-count", buf); + node.add_property ("visible-track-count", buf); snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ()); - node->add_property ("playhead", buf); + node.add_property ("playhead", buf); snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame); - node->add_property ("left-frame", buf); + node.add_property ("left-frame", buf); snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ()); - node->add_property ("y-origin", buf); + node.add_property ("y-origin", buf); - node->add_property ("show-measures", _show_measures ? "yes" : "no"); - node->add_property ("maximised", _maximised ? "yes" : "no"); - node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); - node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); - node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); - node->add_property ("mouse-mode", enum2str(mouse_mode)); - node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no"); + node.add_property ("show-measures", _show_measures ? "yes" : "no"); + node.add_property ("maximised", _maximised ? "yes" : "no"); + node.add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); + node.add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); + node.add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); + node.add_property ("mouse-mode", enum2str(mouse_mode)); + node.add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no"); Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); if (act) { Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); - node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no"); + node.add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no"); } act = ActionManager::get_action (X_("Editor"), X_("show-editor-list")); if (act) { Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); - node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); + node.add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); } snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ()); - node->add_property (X_("editor-list-page"), buf); + node.add_property (X_("editor-list-page"), buf); if (button_bindings) { XMLNode* bb = new XMLNode (X_("Buttons")); button_bindings->save (*bb); - node->add_child_nocopy (*bb); + node.add_child_nocopy (*bb); } - node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no"); + node.add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no"); - node->add_child_nocopy (selection->get_state ()); - node->add_child_nocopy (_regions->get_state ()); + node.add_child_nocopy (selection->get_state ()); + node.add_child_nocopy (_regions->get_state ()); snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration()); - node->add_property ("nudge-clock-value", buf); + node.add_property ("nudge-clock-value", buf); - return *node; + return node; } /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units @@ -3835,7 +3750,7 @@ bool Editor::edit_controls_button_release (GdkEventButton* ev) { if (Keyboard::is_context_menu_event (ev)) { - ARDOUR_UI::instance()->add_route (this); + ARDOUR_UI::instance()->add_route (current_toplevel()); } else if (ev->button == 1) { selection->clear_tracks (); } @@ -3896,12 +3811,6 @@ Editor::cycle_zoom_focus () } void -Editor::ensure_float (Window& win) -{ - win.set_transient_for (*this); -} - -void Editor::pane_allocation_handler (Allocation &alloc, Paned* which) { /* recover or initialize pane positions. do this here rather than earlier because @@ -4292,7 +4201,7 @@ Editor::maximise_editing_space () return; } - fullscreen (); + current_toplevel()->fullscreen (); _maximised = true; } @@ -4304,7 +4213,7 @@ Editor::restore_editing_space () return; } - unfullscreen(); + current_toplevel()->unfullscreen(); _maximised = false; } @@ -4377,13 +4286,14 @@ Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/) bool Editor::on_key_press_event (GdkEventKey* ev) { - return key_press_focus_accelerator_handler (*this, ev); + return key_press_focus_accelerator_handler (*current_toplevel(), ev); } bool Editor::on_key_release_event (GdkEventKey* ev) { - return Gtk::Window::on_key_release_event (ev); + return false; + // return Gtk::Window::on_key_release_event (ev); // return key_press_focus_accelerator_handler (*this, ev); } @@ -5091,7 +5001,7 @@ Editor::first_idle () if (track_views.size() > 1) { Timers::TimerSuspender t; dialog = new MessageDialog ( - *this, + *current_toplevel(), string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME), true ); @@ -5664,7 +5574,7 @@ Editor::super_rapid_screen_update () /* METERING / MIXER STRIPS */ /* update track meters, if required */ - if (is_mapped() && meters_running) { + if (contents().is_mapped() && meters_running) { RouteTimeAxisView* rtv; for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { @@ -5794,12 +5704,15 @@ Editor::session_going_away () stop_step_editing (); - /* get rid of any existing editor mixer strip */ - - WindowTitle title(Glib::get_application_name()); - title += _("Editor"); - - set_title (title.get_string()); + if (own_window()) { + + /* get rid of any existing editor mixer strip */ + + WindowTitle title(Glib::get_application_name()); + title += _("Editor"); + + own_window()->set_title (title.get_string()); + } SessionHandlePtr::session_going_away (); } @@ -6031,3 +5944,55 @@ Editor::ui_parameter_changed (string parameter) } } } + +Gtk::Window* +Editor::use_own_window () +{ + bool new_window = !own_window(); + + Gtk::Window* win = Tabbable::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); + + // win->signal_realize().connect (*this, &Editor::on_realize); + win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler)); + + update_title (); + } + + DisplaySuspender ds; + contents().show_all (); + + /* XXX: this is a bit unfortunate; it would probably + be nicer if we could just call show () above rather + than needing the show_all () + */ + + /* re-hide stuff if necessary */ + editor_list_button_toggled (); + parameter_changed ("show-summary"); + parameter_changed ("show-group-tabs"); + parameter_changed ("show-zoom-tools"); + + /* now reset all audio_time_axis heights, because widgets might need + to be re-hidden + */ + + TimeAxisView *tv; + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + tv = (static_cast<TimeAxisView*>(*i)); + tv->reset_height (); + } + + if (current_mixer_strip) { + current_mixer_strip->hide_things (); + current_mixer_strip->parameter_changed ("mixer-element-visibility"); + } + + return win; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index fab6535f98..5e25936050 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -54,6 +54,7 @@ #include "ardour_button.h" #include "ardour_dialog.h" #include "ardour_dropdown.h" +#include "binding_owners.h" #include "public_editor.h" #include "editing.h" #include "enums.h" @@ -143,6 +144,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void set_session (ARDOUR::Session *); ARDOUR::Session* session() const { return _session; } + Gtk::Window* use_own_window (); + void first_idle (); virtual bool have_idled () const { return _have_idled; } @@ -286,10 +289,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD bool process_midi_export_dialog (MidiExportDialog& dialog, boost::shared_ptr<ARDOUR::MidiRegion> midi_region); - void add_transport_frame (Gtk::Container&); - void add_toplevel_menu (Gtk::Container&); - Gtk::HBox& get_status_bar_packer() { return status_bar_hpacker; } - void set_zoom_focus (Editing::ZoomFocus); Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; } framecnt_t get_current_zoom () const { return samples_per_pixel; } @@ -367,8 +366,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void ensure_float (Gtk::Window&); - void show_window (); - void scroll_tracks_down_line (); void scroll_tracks_up_line (); @@ -561,6 +558,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void color_handler (); bool constructed; + Gtkmm2ext::Bindings key_bindings; // to keep track of the playhead position for control_scroll boost::optional<framepos_t> _control_scroll_target; @@ -783,8 +781,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void timeaxisview_deleted (TimeAxisView *); Gtk::HBox global_hpacker; - Gtk::VBox global_vpacker; - Gtk::VBox vpacker; + VBoxWithBindings global_vpacker; /* Cursor stuff. Do not use directly, use via CursorContext. */ friend class CursorContext; @@ -820,13 +817,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD Gtk::VBox time_bars_vbox; ArdourCanvas::Pixbuf *logo_item; -#if 0 - /* these will be needed when we have canvas rulers */ - ArdourCanvas::Container *minsec_group; - ArdourCanvas::Container *bbt_group; - ArdourCanvas::Container *timecode_group; - ArdourCanvas::Container *frame_group; -#endif ArdourCanvas::Container *tempo_group; ArdourCanvas::Container *meter_group; @@ -1193,7 +1183,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void load_bindings (); Gtkmm2ext::ActionMap editor_action_map; - Gtkmm2ext::Bindings key_bindings; /* CUT/COPY/PASTE */ @@ -1867,10 +1856,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD ArdourCanvas::Rectangle* cd_marker_bar_drag_rect; ArdourCanvas::Rectangle* range_bar_drag_rect; ArdourCanvas::Rectangle* transport_bar_drag_rect; - -#ifdef GTKOSX - ArdourCanvas::Rectangle *bogus_background_rect; -#endif ArdourCanvas::Rectangle *transport_bar_range_rect; ArdourCanvas::Rectangle *transport_bar_preroll_rect; ArdourCanvas::Rectangle *transport_bar_postroll_rect; @@ -2128,8 +2113,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void history_changed (); - Gtk::HBox status_bar_hpacker; - Editing::EditPoint _edit_point; ArdourDropdown edit_point_selector; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 1010dadc54..9b4c29e562 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -2062,11 +2062,8 @@ Editor::register_region_actions () sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint) ); - Glib::RefPtr<Action> a = reg_sens (_region_actions, "choose-top-region", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), false)); - a->set_accel_group (get_accel_group ()); - - a = reg_sens (_region_actions, "choose-top-region-context-menu", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), true)); - a->set_accel_group (get_accel_group ()); + reg_sens (_region_actions, "choose-top-region", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), false)); + reg_sens (_region_actions, "choose-top-region-context-menu", _("Choose Top..."), sigc::bind (sigc::mem_fun (*this, &Editor::change_region_layering_order), true)); _all_region_actions_sensitized = true; diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc index b569037ccc..b6ba2074d4 100644 --- a/gtk2_ardour/editor_audiotrack.cc +++ b/gtk2_ardour/editor_audiotrack.cc @@ -39,7 +39,7 @@ Editor::start_updating_meters () { RouteTimeAxisView* rtv; - if (is_mapped() && _session) { + if (contents().is_mapped() && _session) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { rtv->reset_meter (); @@ -57,7 +57,7 @@ Editor::stop_updating_meters () meters_running = false; - if (is_mapped() && _session) { + if (contents().is_mapped() && _session) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) { rtv->hide_meter (); diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 233a3fbb35..b3668ba194 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -500,7 +500,13 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context, void Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers) { - if (!UIConfiguration::instance().get_autoscroll_editor () || autoscroll_active ()) { + Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel()); + + if (!toplevel) { + return; + } + + if (!UIConfiguration::instance()->get_autoscroll_editor () || autoscroll_active ()) { return; } @@ -557,7 +563,7 @@ Editor::maybe_autoscroll (bool allow_horiz, bool allow_vert, bool from_headers) int x, y; Gdk::ModifierType mask; - get_window()->get_pointer (x, y, mask); + toplevel->get_window()->get_pointer (x, y, mask); if ((allow_horiz && ((x < scrolling_boundary.x0 && leftmost_frame > 0) || x >= scrolling_boundary.x1)) || (allow_vert && ((y < scrolling_boundary.y0 && vertical_adjustment.get_value() > 0)|| y >= scrolling_boundary.y1))) { @@ -578,8 +584,13 @@ Editor::autoscroll_canvas () Gdk::ModifierType mask; frameoffset_t dx = 0; bool no_stop = false; + Gtk::Window* toplevel = dynamic_cast<Gtk::Window*>(contents().get_toplevel()); - get_window()->get_pointer (x, y, mask); + if (!toplevel) { + return false; + } + + toplevel->get_window()->get_pointer (x, y, mask); VisualChange vc; bool vertical_motion = false; @@ -682,7 +693,7 @@ Editor::autoscroll_canvas () int cx; int cy; - translate_coordinates (*_track_canvas, x, y, cx, cy); + toplevel->translate_coordinates (*_track_canvas, x, y, cx, cy); /* clamp x and y to remain within the autoscroll boundary, * which is defined in window coordinates @@ -733,8 +744,8 @@ Editor::autoscroll_canvas () x = min (max ((ArdourCanvas::Coord) x, autoscroll_boundary.x0), autoscroll_boundary.x1); } y = min (max ((ArdourCanvas::Coord) y, autoscroll_boundary.y0), autoscroll_boundary.y1); - - translate_coordinates (*_track_canvas_viewport, x, y, cx, cy); + + toplevel->translate_coordinates (*_track_canvas_viewport, x, y, cx, cy); ArdourCanvas::Duple d = _track_canvas->window_to_canvas (ArdourCanvas::Duple (cx, cy)); ev.x = d.x; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index ba8954f722..1c1f6990c7 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3767,7 +3767,7 @@ MarkerDrag::MarkerDrag (Editor* e, ArdourCanvas::Item* i) assert (_marker); _points.push_back (ArdourCanvas::Duple (0, 0)); - _points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->get_window()))); + _points.push_back (ArdourCanvas::Duple (0, physical_screen_height (_editor->current_toplevel()->get_window()))); } MarkerDrag::~MarkerDrag () @@ -5139,7 +5139,7 @@ RangeMarkerBarDrag::RangeMarkerBarDrag (Editor* e, ArdourCanvas::Item* i, Operat _drag_rect = new ArdourCanvas::Rectangle (_editor->time_line_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, - physical_screen_height (_editor->get_window()))); + physical_screen_height (_editor->current_toplevel()->get_window()))); _drag_rect->hide (); _drag_rect->set_fill_color (UIConfiguration::instance().color ("range drag rect")); diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 9769d616fe..0651d30c1e 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -78,7 +78,7 @@ Editor::show_editor_mixer (bool yn) show_editor_mixer_when_tracks_arrive = false; if (yn) { - Glib::RefPtr<Gdk::Window> win = get_window (); + Glib::RefPtr<Gdk::Window> win = current_toplevel()->get_window (); Glib::RefPtr<Gdk::Screen> screen; if (win) { diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 91f2031efa..a57977007c 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -2782,7 +2782,7 @@ Editor::rename_region () return; } - ArdourDialog d (*this, _("Rename Region"), true, false); + ArdourDialog d (*current_toplevel(), _("Rename Region"), true, false); Entry entry; Label label (_("New name:")); HBox hbox; @@ -7597,7 +7597,7 @@ Editor::fit_tracks (TrackViewList & tracks) double first_y_pos = DBL_MAX; if (h < TimeAxisView::preset_height (HeightSmall)) { - MessageDialog msg (*this, _("There are too many tracks to fit in the current window")); + MessageDialog msg (*current_toplevel(), _("There are too many tracks to fit in the current window")); /* too small to be displayed */ return; } diff --git a/gtk2_ardour/floating_text_entry.cc b/gtk2_ardour/floating_text_entry.cc index d264ee930b..60f10e571b 100644 --- a/gtk2_ardour/floating_text_entry.cc +++ b/gtk2_ardour/floating_text_entry.cc @@ -27,7 +27,7 @@ #include "i18n.h" -FloatingTextEntry::FloatingTextEntry (const std::string& initial_contents) +FloatingTextEntry::FloatingTextEntry (Gtk::Window* parent, const std::string& initial_contents) : Gtk::Window (Gtk::WINDOW_POPUP) , entry_changed (false) { @@ -44,7 +44,10 @@ FloatingTextEntry::FloatingTextEntry (const std::string& initial_contents) entry.signal_activate().connect (sigc::mem_fun (*this, &FloatingTextEntry::activated)); entry.signal_key_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::key_press)); entry.signal_button_press_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::button_press)); - PublicEditor::instance ().signal_focus_out_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::entry_focus_out)); + + if (parent) { + parent->signal_focus_out_event().connect (sigc::mem_fun (*this, &FloatingTextEntry::entry_focus_out)); + } add (entry); } diff --git a/gtk2_ardour/floating_text_entry.h b/gtk2_ardour/floating_text_entry.h index 72e5adc675..116ba34651 100644 --- a/gtk2_ardour/floating_text_entry.h +++ b/gtk2_ardour/floating_text_entry.h @@ -26,7 +26,7 @@ class FloatingTextEntry : public Gtk::Window { public: - FloatingTextEntry (const std::string& initial_contents); + FloatingTextEntry (Gtk::Window* parent, const std::string& initial_contents); sigc::signal1<void,std::string> use_text; diff --git a/gtk2_ardour/meterbridge.cc b/gtk2_ardour/meterbridge.cc index 1a320fa6c2..be7fc4c47d 100644 --- a/gtk2_ardour/meterbridge.cc +++ b/gtk2_ardour/meterbridge.cc @@ -256,7 +256,7 @@ Meterbridge::on_key_press_event (GdkEventKey* ev) if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) { return true; } - return forward_key_press (ev); + return relay_key_press (ev); } bool diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 3dde07be09..ad4025c52f 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -89,8 +89,7 @@ Mixer_UI::instance () } Mixer_UI::Mixer_UI () - : _parent_window (0) - , _visible (false) + : Tabbable (_content, _("Mixer")) , no_track_list_redisplay (false) , in_group_row_change (false) , track_menu (0) @@ -237,19 +236,16 @@ Mixer_UI::Mixer_UI () list_hpane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::pane_allocation_handler), static_cast<Gtk::Paned*> (&list_hpane))); - pack_start (list_hpane, true, true); - - set_name ("MixerWindow"); + _content.pack_start (list_hpane, true, true); update_title (); - add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK); - route_group_display_button_box->show(); route_group_add_button->show(); route_group_remove_button->show(); - show (); + _content.show (); + _content.set_name ("MixerWindow"); global_hpacker.show(); scroller.show(); @@ -299,15 +295,6 @@ Mixer_UI::track_editor_selection () PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection)); } - -void -Mixer_UI::ensure_float (Window& win) -{ - if (_parent_window) { - win.set_transient_for (*_parent_window); - } -} - Gtk::Notebook* Mixer_UI::use_own_window () { @@ -418,7 +405,6 @@ Mixer_UI::hide_window (GdkEventAny *ev) return true; } - void Mixer_UI::add_strips (RouteList& routes) { @@ -871,7 +857,7 @@ Mixer_UI::set_session (Session* sess) refill_favorite_plugins(); XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); - set_state (*node); + set_state (*node, 0); update_title (); @@ -1022,7 +1008,7 @@ Mixer_UI::stop_updating () void Mixer_UI::fast_update_strips () { - if (is_mapped () && _session) { + if (_content.is_mapped () && _session) { for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) { (*i)->fast_update (); } @@ -1030,6 +1016,31 @@ Mixer_UI::fast_update_strips () } void +Mixer_UI::show_window () +{ + Tabbable::show_window (); + + /* show/hide group tabs as required */ + parameter_changed ("show-group-tabs"); + + /* now reset each strips width so the right widgets are shown */ + MixerStrip* ms; + + TreeModel::Children rows = track_model->children(); + TreeModel::Children::iterator ri; + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + ms = (*ri)[track_columns.strip]; + ms->set_width_enum (ms->get_width_enum (), ms->width_owner()); + /* Fix visibility of mixer strip stuff */ + ms->parameter_changed (X_("mixer-element-visibility")); + } + + /* force focus into main area */ + scroller_base.grab_focus (); +} + +void Mixer_UI::set_all_strips_visibility (bool yn) { TreeModel::Children rows = track_model->children(); @@ -1699,23 +1710,6 @@ Mixer_UI::set_strip_width (Width w, bool save) } } -void -Mixer_UI::set_window_pos_and_size () -{ - if (_parent_window) { - _parent_window->resize (m_width, m_height); - _parent_window->move (m_root_x, m_root_y); - } -} - -void -Mixer_UI::get_window_pos_and_size () -{ - if (_parent_window) { - _parent_window->get_position(m_root_x, m_root_y); - _parent_window->get_size(m_width, m_height); - } -} struct PluginStateSorter { public: @@ -1740,7 +1734,7 @@ private: }; int -Mixer_UI::set_state (const XMLNode& node) +Mixer_UI::set_state (const XMLNode& node, int version) { const XMLProperty* prop; XMLNode* geometry; @@ -1792,8 +1786,6 @@ Mixer_UI::set_state (const XMLNode& node) } } - set_window_pos_and_size (); - if ((prop = node.property ("narrow-strips"))) { if (string_is_affirmative (prop->value())) { set_strip_width (Narrow); @@ -1854,7 +1846,7 @@ Mixer_UI::set_state (const XMLNode& node) } XMLNode& -Mixer_UI::get_state (void) +Mixer_UI::get_state () { XMLNode* node = new XMLNode ("Mixer"); @@ -1891,11 +1883,8 @@ Mixer_UI::get_state (void) } node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no"); - node->add_property ("show-mixer", _visible ? "yes" : "no"); - node->add_property ("show-mixer-list", _show_mixer_list ? "yes" : "no"); - node->add_property ("maximised", _maximised ? "yes" : "no"); store_current_favorite_order (); @@ -2171,6 +2160,10 @@ Mixer_UI::new_track_or_bus () void Mixer_UI::update_title () { + if (!own_window()) { + return; + } + if (_session) { string n; @@ -2207,7 +2200,7 @@ Mixer_UI::strip_by_x (int x) for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) { int x1, x2, y; - (*i)->translate_coordinates (*this, 0, 0, x1, y); + (*i)->translate_coordinates (_content, 0, 0, x1, y); x2 = x1 + (*i)->get_width(); if (x >= x1 && x <= x2) { @@ -2267,7 +2260,7 @@ Mixer_UI::toggle_midi_input_active (bool flip_others) void Mixer_UI::maximise_mixer_space () { - if (_maximised) { + if (!own_window()) { return; } @@ -2277,12 +2270,15 @@ Mixer_UI::maximise_mixer_space () win->fullscreen (); _maximised = true; } + + _window->fullscreen (); + _maximised = true; } void Mixer_UI::restore_mixer_space () { - if (!_maximised) { + if (!own_window()) { return; } @@ -2292,6 +2288,9 @@ Mixer_UI::restore_mixer_space () win->unfullscreen(); _maximised = false; } + + own_window()->unfullscreen(); + _maximised = false; } void diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h index 8e4eab1979..4721bf106f 100644 --- a/gtk2_ardour/mixer_ui.h +++ b/gtk2_ardour/mixer_ui.h @@ -42,13 +42,13 @@ #include "ardour/plugin.h" #include "ardour/plugin_manager.h" -<<<<<<< HEAD + #include "gtkmm2ext/visibility_tracker.h" #include "gtkmm2ext/dndtreeview.h" #include "gtkmm2ext/treeutils.h" -======= ->>>>>>> the basics of tabbed +#include "gtkmm2ext/tabbable.h" + #include "enums.h" #include "mixer_actor.h" @@ -62,7 +62,6 @@ class PluginSelector; class MixerGroupTabs; class MonitorSection; -<<<<<<< HEAD class PluginTreeStore : public Gtk::TreeStore { public: @@ -76,20 +75,15 @@ protected: virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const; }; -class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor, public Gtkmm2ext::VisibilityTracker -======= -class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor ->>>>>>> the basics of tabbed +class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public MixerActor, public Gtkmm2ext::VisibilityTracker { public: static Mixer_UI* instance(); ~Mixer_UI(); - Gtk::Window* own_window() const { return _parent_window; } - Gtk::Notebook* use_own_window(); + Gtk::Window* use_own_window (); + void show_window (); - bool visible() const { return _visible; } - void set_session (ARDOUR::Session *); void track_editor_selection (); @@ -101,22 +95,18 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO void unselect_strip_in_display (MixerStrip*); void select_strip_in_display (MixerStrip*); - XMLNode& get_state (void); - int set_state (const XMLNode& ); + XMLNode& get_state (); + int set_state (const XMLNode&, int /* version */); void show_mixer_list (bool yn); void show_monitor_section (bool); - - void show_window (); - bool hide_window (GdkEventAny *ev); + void show_strip (MixerStrip *); void hide_strip (MixerStrip *); void maximise_mixer_space(); void restore_mixer_space(); - void ensure_float (Gtk::Window&); - MonitorSection* monitor_section() const { return _monitor_section; } void deselect_all_strip_processors(); @@ -124,23 +114,22 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO void select_none (); + bool window_not_visible () const; + protected: void set_route_targets_for_operation (); private: Mixer_UI (); - static Mixer_UI* _instance; - - Gtk::Window* _parent_window; - bool _visible; - - Gtk::HBox global_hpacker; - Gtk::VBox global_vpacker; - Gtk::ScrolledWindow scroller; - Gtk::EventBox scroller_base; - Gtk::HBox scroller_hpacker; - Gtk::VBox mixer_scroller_vpacker; - Gtk::VBox list_vpacker; + static Mixer_UI* _instance; + Gtk::VBox _content; + Gtk::HBox global_hpacker; + Gtk::VBox global_vpacker; + Gtk::ScrolledWindow scroller; + Gtk::EventBox scroller_base; + Gtk::HBox scroller_hpacker; + Gtk::VBox mixer_scroller_vpacker; + Gtk::VBox list_vpacker; Gtk::Label group_display_button_label; Gtk::Button group_display_button; Gtk::ScrolledWindow track_display_scroller; @@ -373,7 +362,7 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO ======= void create_own_window (); - + >>>>>>> the basics of tabbed /// true if we are in fullscreen mode bool _maximised; @@ -383,5 +372,3 @@ class Mixer_UI : public Gtk::VBox, public PBD::ScopedConnectionList, public ARDO }; #endif /* __ardour_mixer_ui_h__ */ - - diff --git a/gtk2_ardour/monitor_section.cc b/gtk2_ardour/monitor_section.cc index 64a9ec65ef..275a60f8f3 100644 --- a/gtk2_ardour/monitor_section.cc +++ b/gtk2_ardour/monitor_section.cc @@ -466,7 +466,7 @@ MonitorSection::MonitorSection (Session* s) _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL); } _tearoff->tearoff_window().set_title (X_("Monitor")); - _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false); + _tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), (Gtk::Window*) 0), false); update_output_display (); update_processor_box (); diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc index 7b9918b40f..f576a4ea00 100644 --- a/gtk2_ardour/panner2d.cc +++ b/gtk2_ardour/panner2d.cc @@ -1013,7 +1013,7 @@ Panner2dWindow::set_width () bool Panner2dWindow::on_key_press_event (GdkEventKey* event) { - return relay_key_press (event, &PublicEditor::instance()); + return relay_key_press (event, 0); } bool diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc index 256a90d1c1..833055eff7 100644 --- a/gtk2_ardour/plugin_ui.cc +++ b/gtk2_ardour/plugin_ui.cc @@ -374,7 +374,7 @@ PluginUIWindow::on_key_press_event (GdkEventKey* event) no widgets in this window that we want to have key focus. */ - return relay_key_press (event, &PublicEditor::instance()); + return relay_key_press (event, 0); } else { return relay_key_press (event, this); } diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 68beac400a..4271f313fd 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -2002,7 +2002,7 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w) const XMLNode* ui_xml = _session->extra_xml (X_("UI")); if (ui_xml) { - wp->set_state (*ui_xml); + wp->set_state (*ui_xml, 0); } void* existing_ui = p->get_ui (); @@ -3305,7 +3305,7 @@ ProcessorWindowProxy::session_handle() } XMLNode& -ProcessorWindowProxy::get_state () const +ProcessorWindowProxy::get_state () { XMLNode *node; node = &ProxyBase::get_state(); @@ -3313,8 +3313,8 @@ ProcessorWindowProxy::get_state () const return *node; } -void -ProcessorWindowProxy::set_state (const XMLNode& node) +int +ProcessorWindowProxy::set_state (const XMLNode& node, int /*version*/) { XMLNodeList children = node.children (); XMLNodeList::const_iterator i = children.begin (); @@ -3333,7 +3333,7 @@ ProcessorWindowProxy::set_state (const XMLNode& node) } } - ProxyBase::set_state(node); + return ProxyBase::set_state (node, 0); } Gtk::Window* diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h index d904e13c74..0610af72d7 100644 --- a/gtk2_ardour/processor_box.h +++ b/gtk2_ardour/processor_box.h @@ -78,31 +78,31 @@ class ProcessorBox; class ProcessorWindowProxy : public WM::ProxyBase { public: - ProcessorWindowProxy (std::string const &, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>); - ~ProcessorWindowProxy(); - - Gtk::Window* get (bool create = false); - - boost::weak_ptr<ARDOUR::Processor> processor () const { - return _processor; - } - - ARDOUR::SessionHandlePtr* session_handle(); - void toggle(); - void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; } - - void set_state (const XMLNode&); - XMLNode& get_state () const; - + ProcessorWindowProxy (std::string const &, ProcessorBox *, boost::weak_ptr<ARDOUR::Processor>); + ~ProcessorWindowProxy(); + + Gtk::Window* get (bool create = false); + + boost::weak_ptr<ARDOUR::Processor> processor () const { + return _processor; + } + + ARDOUR::SessionHandlePtr* session_handle(); + void toggle(); + void set_custom_ui_mode(bool use_custom) { want_custom = use_custom; } + + int set_state (const XMLNode&, int); + XMLNode& get_state (); + private: - ProcessorBox* _processor_box; - boost::weak_ptr<ARDOUR::Processor> _processor; - bool is_custom; - bool want_custom; - bool _valid; - - void processor_going_away (); - PBD::ScopedConnection going_away_connection; + ProcessorBox* _processor_box; + boost::weak_ptr<ARDOUR::Processor> _processor; + bool is_custom; + bool want_custom; + bool _valid; + + void processor_going_away (); + PBD::ScopedConnection going_away_connection; }; class ProcessorEntry : public Gtkmm2ext::DnDVBoxChild, public sigc::trackable diff --git a/gtk2_ardour/public_editor.cc b/gtk2_ardour/public_editor.cc index e88f273c87..11f823e0ff 100644 --- a/gtk2_ardour/public_editor.cc +++ b/gtk2_ardour/public_editor.cc @@ -19,6 +19,8 @@ #include "public_editor.h" +#include "i18n.h" + PublicEditor* PublicEditor::_instance = 0; const int PublicEditor::window_border_width = 12; @@ -28,9 +30,8 @@ const int PublicEditor::horizontal_spacing = 6; sigc::signal<void> PublicEditor::DropDownKeys; -PublicEditor::PublicEditor () - : Window (Gtk::WINDOW_TOPLEVEL) - , VisibilityTracker (*((Gtk::Window*)this)) +PublicEditor::PublicEditor (Gtk::Widget& content) + : Tabbable (content, _("Editor")) , _suspend_route_redisplay_counter (0) { } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 90ee30dbca..f119cca747 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -43,6 +43,7 @@ #include "canvas/fwd.h" #include "gtkmm2ext/actions.h" +#include "gtkmm2ext/tabbable.h" #include "gtkmm2ext/visibility_tracker.h" #include "editing.h" @@ -105,9 +106,9 @@ using ARDOUR::framecnt_t; * of PublicEditor need not be recompiled if private methods or member variables * change. */ -class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, public Gtkmm2ext::VisibilityTracker { +class PublicEditor : public Gtkmm2ext::Tabbable { public: - PublicEditor (); + PublicEditor (Gtk::Widget& content); virtual ~PublicEditor (); /** @return Singleton PublicEditor instance */ @@ -232,8 +233,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi virtual void export_range () = 0; virtual void register_actions () = 0; - virtual void add_transport_frame (Gtk::Container&) = 0; - virtual void add_toplevel_menu (Gtk::Container&) = 0; virtual void set_zoom_focus (Editing::ZoomFocus) = 0; virtual Editing::ZoomFocus get_zoom_focus () const = 0; virtual framecnt_t get_current_zoom () const = 0; @@ -267,8 +266,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi /** @return true if the playhead is currently being dragged, otherwise false */ virtual bool dragging_playhead () const = 0; - virtual void ensure_float (Gtk::Window&) = 0; - virtual void show_window () = 0; virtual framepos_t leftmost_sample() const = 0; virtual framecnt_t current_page_samples() const = 0; virtual double visible_canvas_height () const = 0; @@ -442,11 +439,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi PBD::Signal0<void> SnapChanged; PBD::Signal0<void> MouseModeChanged; - Gtk::Notebook& tabs() { return _tabs; } - protected: - Gtk::Notebook _tabs; - friend class DisplaySuspender; virtual void suspend_route_redisplay () = 0; virtual void resume_route_redisplay () = 0; diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index ee5ebd4594..f08b0ff6ce 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -1720,6 +1720,7 @@ private: RCOptionEditor::RCOptionEditor () : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME)) + , Tabbable (*this, _("Preferences")) , _rc_config (Config) , _mixer_strip_visibility ("mixer-element-visibility") { @@ -1831,6 +1832,7 @@ RCOptionEditor::RCOptionEditor () /* TRANSPORT */ + add_option (_("Transport"), new OptionEditorHeading (S_("Playhead Behaviour"))); add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options"))); BoolOption* tsf; diff --git a/gtk2_ardour/rc_option_editor.h b/gtk2_ardour/rc_option_editor.h index 1b543e3aaf..a74df7cfde 100644 --- a/gtk2_ardour/rc_option_editor.h +++ b/gtk2_ardour/rc_option_editor.h @@ -20,6 +20,8 @@ #ifndef __gtk_ardour_rc_option_editor_h__ #define __gtk_ardour_rc_option_editor_h__ +#include "gtkmm2ext/tabbable.h" + #include "option_editor.h" #include "visibility_group.h" @@ -32,7 +34,7 @@ */ /** Editor for options which are obtained from and written back to one of the .rc files. */ -class RCOptionEditor : public OptionEditor +class RCOptionEditor : public OptionEditor, public Gtkmm2ext::Tabbable { public: RCOptionEditor (); diff --git a/gtk2_ardour/region_layering_order_editor.cc b/gtk2_ardour/region_layering_order_editor.cc index 759b69fae1..a8ab1d6904 100644 --- a/gtk2_ardour/region_layering_order_editor.cc +++ b/gtk2_ardour/region_layering_order_editor.cc @@ -222,7 +222,7 @@ RegionLayeringOrderEditor::on_key_press_event (GdkEventKey* ev) } if (!handled) { - handled = key_press_focus_accelerator_handler (editor, ev); + handled = relay_key_press (ev, 0); } if (!handled) { diff --git a/gtk2_ardour/step_entry.cc b/gtk2_ardour/step_entry.cc index 366a9e199a..89859651f1 100644 --- a/gtk2_ardour/step_entry.cc +++ b/gtk2_ardour/step_entry.cc @@ -504,7 +504,7 @@ StepEntry::on_key_press_event (GdkEventKey* ev) } } - return forward_key_press (ev); + return relay_key_press (ev); } bool diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 60498b9fac..3c7945993a 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -297,39 +297,28 @@ ARDOUR_UI_UTILS::gdk_color_to_rgba (Gdk::Color const& c) bool ARDOUR_UI_UTILS::relay_key_press (GdkEventKey* ev, Gtk::Window* win) { - - if (!key_press_focus_accelerator_handler (*win, ev)) { - if (!PublicEditor::_instance) { - /* early key press in pre-main-window-dialogs, no editor yet */ - return false; - } - PublicEditor& ed (PublicEditor::instance()); - return ed.on_key_press_event(ev); - } else { - return true; + 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); } } bool -ARDOUR_UI_UTILS::forward_key_press (GdkEventKey* ev) +ARDOUR_UI_UTILS::emulate_key_event (unsigned int keyval) { - return PublicEditor::instance().on_key_press_event(ev); -} - -bool -ARDOUR_UI_UTILS::emulate_key_event (Gtk::Widget* w, unsigned int keyval) -{ - GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET(w->gobj())); + GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET(ARDOUR_UI::instance()->main_window().gobj())); GdkKeymap *keymap = gdk_keymap_get_for_display (display); GdkKeymapKey *keymapkey = NULL; gint n_keys; - + if (!gdk_keymap_get_entries_for_keyval(keymap, keyval, &keymapkey, &n_keys)) return false; if (n_keys !=1) { g_free(keymapkey); return false;} GdkEventKey ev; ev.type = GDK_KEY_PRESS; - ev.window = gtk_widget_get_window(GTK_WIDGET(w->gobj())); + ev.window = ARDOUR_UI::instance()->main_window().get_window()->gobj(); ev.send_event = FALSE; ev.time = 0; ev.state = 0; @@ -340,9 +329,9 @@ ARDOUR_UI_UTILS::emulate_key_event (Gtk::Widget* w, unsigned int keyval) ev.group = keymapkey[0].group; g_free(keymapkey); - forward_key_press(&ev); + relay_key_press(&ev); ev.type = GDK_KEY_RELEASE; - return forward_key_press(&ev); + return relay_key_press(&ev); } static string diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h index c6df938394..d883e74fa5 100644 --- a/gtk2_ardour/utils.h +++ b/gtk2_ardour/utils.h @@ -67,10 +67,9 @@ void set_color_from_rgba (Gdk::Color&, uint32_t); uint32_t gdk_color_to_rgba (Gdk::Color const&); uint32_t contrasting_text_color (uint32_t c); -bool relay_key_press (GdkEventKey* ev, Gtk::Window* win); -bool forward_key_press (GdkEventKey* ev); +bool relay_key_press (GdkEventKey* ev, Gtk::Window* win = 0); bool key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev); -bool emulate_key_event (Gtk::Widget*, unsigned int); +bool emulate_key_event (unsigned int); Glib::RefPtr<Gdk::Pixbuf> get_xpm (std::string); std::vector<std::string> get_icon_sets (); diff --git a/gtk2_ardour/video_monitor.cc b/gtk2_ardour/video_monitor.cc index ece1856d54..0ad90d4520 100644 --- a/gtk2_ardour/video_monitor.cc +++ b/gtk2_ardour/video_monitor.cc @@ -255,9 +255,7 @@ VideoMonitor::is_started () void VideoMonitor::forward_keyevent (unsigned int keyval) { - Editor* ed = dynamic_cast<Editor*>(&PublicEditor::instance()); - if (!ed) return; - emulate_key_event(ed, keyval); + emulate_key_event (keyval); } void diff --git a/gtk2_ardour/window_manager.cc b/gtk2_ardour/window_manager.cc index b476787926..3ab742199d 100644 --- a/gtk2_ardour/window_manager.cc +++ b/gtk2_ardour/window_manager.cc @@ -170,269 +170,23 @@ Manager::set_transient_for (Gtk::Window* parent) /*-------------------------*/ -ProxyBase::ProxyBase (const string& name, const std::string& menu_name) - : _name (name) - , _menu_name (menu_name) - , _window (0) - , _visible (false) - , _x_off (-1) - , _y_off (-1) - , _width (-1) - , _height (-1) - , vistracker (0) +ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name) + : WindowProxy (name, menu_name) { } -ProxyBase::ProxyBase (const string& name, const std::string& menu_name, const XMLNode& node) - : _name (name) - , _menu_name (menu_name) - , _window (0) - , _visible (false) - , _x_off (-1) - , _y_off (-1) - , _width (-1) - , _height (-1) - , vistracker (0) +ProxyBase::ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode& node) + : WindowProxy (name, menu_name, node) { - set_state (node); -} - -ProxyBase::~ProxyBase () -{ - delete vistracker; - delete _window; -} - -void -ProxyBase::set_state (const XMLNode& node) -{ - XMLNodeList children = node.children (); - - XMLNodeList::const_iterator i = children.begin (); - - while (i != children.end()) { - XMLProperty* prop = (*i)->property (X_("name")); - if ((*i)->name() == X_("Window") && prop && prop->value() == _name) { - break; - } - - ++i; - } - - if (i != children.end()) { - - XMLProperty* prop; - - if ((prop = (*i)->property (X_("visible"))) != 0) { - _visible = PBD::string_is_affirmative (prop->value ()); - } - - if ((prop = (*i)->property (X_("x-off"))) != 0) { - _x_off = atoi (prop->value()); - } - if ((prop = (*i)->property (X_("y-off"))) != 0) { - _y_off = atoi (prop->value()); - } - if ((prop = (*i)->property (X_("x-size"))) != 0) { - _width = atoi (prop->value()); - } - if ((prop = (*i)->property (X_("y-size"))) != 0) { - _height = atoi (prop->value()); - } - } - - /* if we have a window already, reset its properties */ - - if (_window) { - setup (); - } -} - -void -ProxyBase::set_action (Glib::RefPtr<Gtk::Action> act) -{ - _action = act; -} - -std::string -ProxyBase::action_name() const -{ - return string_compose (X_("toggle-%1"), _name); -} - -void -ProxyBase::toggle() -{ - if (!_window) { - (void) get (true); - assert (_window); - /* XXX this is a hack - the window object should really - ensure its components are all visible. sigh. - */ - _window->show_all(); - /* we'd like to just call this and nothing else */ - _window->present (); - - if (_width != -1 && _height != -1) { - _window->set_default_size (_width, _height); - } - if (_x_off != -1 && _y_off != -1) { - _window->move (_x_off, _y_off); - } - - } else { - if (_window->is_mapped()) { - save_pos_and_size(); - } - vistracker->cycle_visibility (); - if (_window->is_mapped()) { - if (_width != -1 && _height != -1) { - _window->set_default_size (_width, _height); - } - if (_x_off != -1 && _y_off != -1) { - _window->move (_x_off, _y_off); - } - } - } -} - -XMLNode& -ProxyBase::get_state () const -{ - XMLNode* node = new XMLNode (X_("Window")); - char buf[32]; - - node->add_property (X_("name"), _name); - - if (_window && vistracker) { - - /* we have a window, so use current state */ - - _visible = vistracker->partially_visible (); - if (_visible) { - _window->get_position (_x_off, _y_off); - _window->get_size (_width, _height); - } - } - - node->add_property (X_("visible"), _visible? X_("yes") : X_("no")); - - snprintf (buf, sizeof (buf), "%d", _x_off); - node->add_property (X_("x-off"), buf); - snprintf (buf, sizeof (buf), "%d", _y_off); - node->add_property (X_("y-off"), buf); - snprintf (buf, sizeof (buf), "%d", _width); - node->add_property (X_("x-size"), buf); - snprintf (buf, sizeof (buf), "%d", _height); - node->add_property (X_("y-size"), buf); - - return *node; -} - -void -ProxyBase::drop_window () -{ - if (_window) { - _window->hide (); - delete _window; - _window = 0; - delete vistracker; - vistracker = 0; - } -} - -void -ProxyBase::use_window (Gtk::Window& win) -{ - drop_window (); - _window = &win; - setup (); } void ProxyBase::setup () { - assert (_window); - - vistracker = new Gtkmm2ext::VisibilityTracker (*_window); - _window->signal_delete_event().connect (sigc::mem_fun (*this, &ProxyBase::delete_event_handler)); - - if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) { - /* cancel any mouse-based positioning */ - _window->set_position (Gtk::WIN_POS_NONE); - } - - if (_width != -1 && _height != -1) { - _window->set_default_size (_width, _height); - } - - if (_x_off != -1 && _y_off != -1) { - _window->move (_x_off, _y_off); - } + WindowProxy::setup (); set_session(_session); -} - -void -ProxyBase::show () -{ - get (true); - assert (_window); - _window->show (); -} - -void -ProxyBase::maybe_show () -{ - if (_visible) { - show (); - } -} - -void -ProxyBase::show_all () -{ - get (true); - assert (_window); - _window->show_all (); -} - -void -ProxyBase::present () -{ - get (true); - assert (_window); - - _window->show_all (); - _window->present (); - - /* turn off any mouse-based positioning */ - _window->set_position (Gtk::WIN_POS_NONE); -} +} -void -ProxyBase::hide () -{ - if (_window) { - save_pos_and_size(); - _window->hide (); - } -} - -bool -ProxyBase::delete_event_handler (GdkEventAny* /*ev*/) -{ - hide(); - return true; -} - -void -ProxyBase::save_pos_and_size () -{ - if (_window) { - _window->get_position (_x_off, _y_off); - _window->get_size (_width, _height); - } -} /*-----------------------*/ ProxyTemporary::ProxyTemporary (const string& name, Gtk::Window* win) diff --git a/gtk2_ardour/window_manager.h b/gtk2_ardour/window_manager.h index 6e89be3b26..5d1349f258 100644 --- a/gtk2_ardour/window_manager.h +++ b/gtk2_ardour/window_manager.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2013 Paul Davis + Copyright (C) 2013 Paul Davis - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -27,20 +27,22 @@ #include <glibmm/refptr.h> #include <sigc++/trackable.h> +#include "gtkmm2ext/window_proxy.h" + class XMLNode; namespace Gtk { - class Window; - class Action; +class Window; +class Action; } namespace Gtkmm2ext { - class VisibilityTracker; +class VisibilityTracker; } namespace ARDOUR { - class Session; - class SessionHandlePtr; +class Session; +class SessionHandlePtr; } namespace WM { @@ -50,192 +52,156 @@ class ProxyBase; class Manager : public ARDOUR::SessionHandlePtr { public: - static Manager& instance(); + static Manager& instance(); - void register_window (ProxyBase*); - void remove (const ProxyBase*); - void toggle_window (ProxyBase*); - void show_visible () const; - void set_session (ARDOUR::Session*); - void add_state (XMLNode&) const; + void register_window (ProxyBase*); + void remove (const ProxyBase*); + void toggle_window (ProxyBase*); + void show_visible () const; + void set_session (ARDOUR::Session*); + void add_state (XMLNode&) const; - /* HACK HACK HACK */ - void set_transient_for (Gtk::Window*); - Gtk::Window* transient_parent() const { return current_transient_parent; } + /* HACK HACK HACK */ + void set_transient_for (Gtk::Window*); + Gtk::Window* transient_parent() const { return current_transient_parent; } - private: - typedef std::list<ProxyBase*> Windows; - Windows _windows; - Glib::RefPtr<Gtk::ActionGroup> window_actions; - Gtk::Window* current_transient_parent; + private: + typedef std::list<ProxyBase*> Windows; + Windows _windows; + Glib::RefPtr<Gtk::ActionGroup> window_actions; + Gtk::Window* current_transient_parent; - Manager(); - ~Manager(); + Manager(); + ~Manager(); - static Manager* _instance; + static Manager* _instance; }; - -class ProxyBase : public ARDOUR::SessionHandlePtr, public sigc::trackable { + +class ProxyBase : public ARDOUR::SessionHandlePtr, public Gtkmm2ext::WindowProxy +{ public: - ProxyBase (const std::string& name, const std::string& menu_name); - ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&); - virtual ~ProxyBase(); - - void show (); - void show_all (); - void hide (); - void present (); - void maybe_show (); - - bool visible() const { return _visible; } - const std::string& name() const { return _name; } - const std::string& menu_name() const { return _menu_name; } - - std::string action_name() const; - void set_action (Glib::RefPtr<Gtk::Action>); - Glib::RefPtr<Gtk::Action> action() const { return _action; }; - - void drop_window (); - void use_window (Gtk::Window&); - - virtual Gtk::Window* get (bool create = false) = 0; - - virtual void toggle (); - - void set_state (const XMLNode&); - XMLNode& get_state () const; - - virtual ARDOUR::SessionHandlePtr* session_handle () = 0; - - operator bool() const { return _window != 0; } + ProxyBase (const std::string& name, const std::string& menu_name); + ProxyBase (const std::string& name, const std::string& menu_name, const XMLNode&); + + virtual ARDOUR::SessionHandlePtr* session_handle () = 0; protected: - std::string _name; - std::string _menu_name; - Glib::RefPtr<Gtk::Action> _action; - Gtk::Window* _window; - mutable bool _visible; ///< true if the window should be visible on startup - mutable int _x_off; ///< x position - mutable int _y_off; ///< y position - mutable int _width; ///< width - mutable int _height; ///< height - Gtkmm2ext::VisibilityTracker* vistracker; - - void save_pos_and_size (); - bool delete_event_handler (GdkEventAny *ev); - - void setup (); + void setup (); }; - -class ProxyTemporary: public ProxyBase { + +class ProxyTemporary: public ProxyBase +{ public: - ProxyTemporary (const std::string& name, Gtk::Window* win); - ~ProxyTemporary(); - - Gtk::Window* get (bool create = false) { - (void) create; - return _window; - } - - Gtk::Window* operator->() { - return _window; - } - - ARDOUR::SessionHandlePtr* session_handle (); + ProxyTemporary (const std::string& name, Gtk::Window* win); + ~ProxyTemporary(); + + Gtk::Window* get (bool create = false) { + (void) create; + return _window; + } + + Gtk::Window* operator->() { + return _window; + } + + ARDOUR::SessionHandlePtr* session_handle (); }; template<typename T> -class ProxyWithConstructor: public ProxyBase { +class ProxyWithConstructor: public ProxyBase +{ public: - ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c) - : ProxyBase (name, menu_name) , creator (c) {} - - ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node) - : ProxyBase (name, menu_name, *node) , creator (c) {} - - Gtk::Window* get (bool create = false) { - if (!_window) { - if (!create) { - return 0; - } + ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c) + : ProxyBase (name, menu_name) , creator (c) {} + + ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node) + : ProxyBase (name, menu_name, *node) , creator (c) {} + + Gtk::Window* get (bool create = false) { + if (!_window) { + if (!create) { + return 0; + } _window = dynamic_cast<Gtk::Window*> (creator ()); - if (_window) { - setup (); - } - } - - return _window; - } - - T* operator->() { - return dynamic_cast<T*> (get (true)); - } - - ARDOUR::SessionHandlePtr* session_handle () { - /* may return null */ - return dynamic_cast<T*> (_window); - } - - void set_session(ARDOUR::Session *s) { - SessionHandlePtr::set_session (s); - ARDOUR::SessionHandlePtr* sp = session_handle (); - if (sp) { - sp->set_session (s); - dynamic_cast<T*>(_window)->set_session(s); - } - } - - private: - boost::function<T*()> creator; + if (_window) { + setup (); + } + } + + return _window; + } + + T* operator->() { + return dynamic_cast<T*> (get (true)); + } + + ARDOUR::SessionHandlePtr* session_handle () { + /* may return null */ + return dynamic_cast<T*> (_window); + } + + void set_session(ARDOUR::Session *s) { + SessionHandlePtr::set_session (s); + ARDOUR::SessionHandlePtr* sp = session_handle (); + if (sp) { + sp->set_session (s); + dynamic_cast<T*>(_window)->set_session(s); + } + } + + private: + boost::function<T*()> creator; +>>>>>>> first compilable version of tabbable design. }; template<typename T> -class Proxy : public ProxyBase { +class Proxy : public ProxyBase +{ public: - Proxy (const std::string& name, const std::string& menu_name) - : ProxyBase (name, menu_name) {} - - Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node) - : ProxyBase (name, menu_name, *node) {} - - Gtk::Window* get (bool create = false) { - if (!_window) { - if (!create) { - return 0; - } - - _window = new T (); - - if (_window) { - setup (); - } - } - - return _window; - } - - T* operator->() { - return dynamic_cast<T*> (get(true)); - } - - ARDOUR::SessionHandlePtr* session_handle () { - /* may return null */ - return dynamic_cast<T*> (_window); - } - - void set_session(ARDOUR::Session *s) { - SessionHandlePtr::set_session (s); - ARDOUR::SessionHandlePtr* sp = session_handle (); - if (sp) { - sp->set_session (s); - dynamic_cast<T*>(_window)->set_session(s); - } - } - + Proxy (const std::string& name, const std::string& menu_name) + : ProxyBase (name, menu_name) {} + + Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node) + : ProxyBase (name, menu_name, *node) {} + + Gtk::Window* get (bool create = false) { + if (!_window) { + if (!create) { + return 0; + } + + _window = new T (); + + if (_window) { + setup (); + } + } + + return _window; + } + + T* operator->() { + return dynamic_cast<T*> (get(true)); + } + + ARDOUR::SessionHandlePtr* session_handle () { + /* may return null */ + return dynamic_cast<T*> (_window); + } + + void set_session(ARDOUR::Session *s) { + SessionHandlePtr::set_session (s); + ARDOUR::SessionHandlePtr* sp = session_handle (); + if (sp) { + sp->set_session (s); + dynamic_cast<T*>(_window)->set_session(s); + } + } + private: - boost::function<T*()> creator; + boost::function<T*()> creator; }; } /* namespace */ |