save/restore tabbable state
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 9 Jul 2015 16:40:51 +0000 (12:40 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 22 Feb 2016 20:31:21 +0000 (15:31 -0500)
13 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/rc_option_editor.cc
gtk2_ardour/rc_option_editor.h
gtk2_ardour/window_manager.cc
libs/gtkmm2ext/gtkmm2ext/tabbable.h
libs/gtkmm2ext/gtkmm2ext/window_proxy.h
libs/gtkmm2ext/tabbable.cc
libs/gtkmm2ext/window_proxy.cc

index 18bd8721331e73aa8d3d39361d318ac49f79273c..9e17d52e5e7eb93459669cb2315de04d93cb8f78 100644 (file)
@@ -427,15 +427,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                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);
        }
 
+       /* Separate windows */
+       
        WM::Manager::instance().register_window (&key_editor);
-       // WM::Manager::instance().register_window (&rc_option_editor);
        WM::Manager::instance().register_window (&session_option_editor);
        WM::Manager::instance().register_window (&speaker_config_window);
        WM::Manager::instance().register_window (&about);
index 1a89311ec388285707b26d6b49c2c80e2d6c14ba..20d2153005a5370ed7103bfe062accf7f467cf71 100644 (file)
@@ -665,6 +665,10 @@ ARDOUR_UI::save_ardour_state ()
 
        window_node->add_child_nocopy (*tearoff_node);
 
+       XMLNode& enode (editor->get_state());
+       XMLNode& mnode (mixer->get_state());
+       XMLNode& bnode (meterbridge->get_state());
+
        Config->add_extra_xml (*window_node);
        Config->add_extra_xml (audio_midi_setup->get_state());
 
@@ -672,10 +676,6 @@ ARDOUR_UI::save_ardour_state ()
 
        UIConfiguration::instance().save_state ();
 
-       XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
-       XMLNode& mnode (mixer->get_state());
-       XMLNode& bnode (meterbridge->get_state());
-
        if (_session) {
                _session->add_instant_xml (enode);
                _session->add_instant_xml (mnode);
@@ -686,6 +686,7 @@ ARDOUR_UI::save_ardour_state ()
        } else {
                Config->add_instant_xml (enode);
                Config->add_instant_xml (mnode);
+               Config->add_instant_xml (bnode);
                if (location_ui) {
                        Config->add_instant_xml (location_ui->ui().get_state ());
                }
index aed4330c4687e188167e8a50c4ba3bac2c5aee53..f1dd0b2edd51cb018901e09b31d78e08c1de06fe 100644 (file)
@@ -1336,6 +1336,8 @@ Editor::set_session (Session *t)
           the selected Marker; this needs the LocationMarker list to be available.
        */
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
+
+       cerr << "Editor - found state node " << node << endl;
        set_state (*node, Stateful::loading_state_version);
 
        /* catch up with the playhead */
@@ -2182,7 +2184,6 @@ int
 Editor::set_state (const XMLNode& node, int version)
 {
        const XMLProperty* prop;
-
        set_id (node);
 
        Tabbable::set_state (node, version);
@@ -2410,82 +2411,81 @@ Editor::set_state (const XMLNode& node, int version)
 XMLNode&
 Editor::get_state ()
 {
-       XMLNode& node (Tabbable::get_state());
+       XMLNode* node = new XMLNode (X_("Editor"));
        char buf[32];
 
        id().print (buf, sizeof (buf));
-       node.add_property ("id", buf);
+       node->add_property ("id", buf);
 
-#if 0
-       // need to save this somehow 
+       node->add_child_nocopy (Tabbable::get_state());
+       
        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");
+       node->add_property("edit-horizontal-pane-pos", string(buf));
+       node->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
+       node->add_property("edit-vertical-pane-pos", string(buf));
        
-       maybe_add_mixer_strip_width (node);
+       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
@@ -5935,11 +5935,11 @@ Editor::ui_parameter_changed (string parameter)
 }
 
 Gtk::Window*
-Editor::use_own_window ()
+Editor::use_own_window (bool and_fill_it)
 {
        bool new_window = !own_window();
        
-       Gtk::Window* win = Tabbable::use_own_window ();
+       Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
 
        if (win && new_window) {
                win->set_name ("EditorWindow");
index 8f00fe110b56369a5240a199f9a3e7f75c1af71c..bd20ba250fcd91d1377b2310b3497f20a1ba3797 100644 (file)
@@ -144,7 +144,7 @@ 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 ();
+       Gtk::Window* use_own_window (bool and_fill_it);
        
        void             first_idle ();
        virtual bool     have_idled () const { return _have_idled; }
index ad4025c52f79f4d756cfc6b4589cca9443be60db..ed2fdfdde5ec7df472d5bbd7c75f8434033a7a6f 100644 (file)
@@ -295,50 +295,26 @@ Mixer_UI::track_editor_selection ()
        PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection));
 }
 
-Gtk::Notebook*
-Mixer_UI::use_own_window ()
-{
-       /* This is called after a drop of a tab onto the root window. Its
-        * responsibility is to return the notebook that this Mixer_UI should
-        * be packed into before the drop handling is completed. It is not
-        * responsible for actually taking care of this packing
-        */
-
-       if (_parent_window) {
-               return 0;
-       }
-
-       create_own_window ();
-
-       return (Gtk::Notebook*) _parent_window->get_child();
-}
-
 void
-Mixer_UI::create_own_window ()
+Gtk::Window*
+Mixer_UI::use_own_window (bool and_fill_it)
 {
-       if (_parent_window) {
-               return;
-       }
+       bool new_window = !own_window();
 
-       _parent_window = new Window (Gtk::WINDOW_TOPLEVEL);
-       Notebook* notebook = manage (new Notebook);
+       Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
 
-       notebook->set_show_tabs (false);
-       notebook->show_all ();
 
-       _parent_window->add (*notebook);
-
-       /* allow parent window to become the key focus window */
-       _parent_window->set_flags (CAN_FOCUS);
-
-       /* handle window manager close/delete event sensibly */
-       _parent_window->signal_delete_event().connect (sigc::mem_fun (*this, &Mixer_UI::hide_window));
+       if (win && new_window) {
+               win->set_name ("MixerWindow");
+               ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Mixer"), this);
+               win->signal_scroll_event().connect (sigc::mem_fun (*this, &Mixer_UI::on_scroll_event), false);
+               win->set_data ("ardour-bindings", bindings);
+               update_title ();
+       }
 
-       set_window_pos_and_size ();
-       update_title ();
+       return win;
 }
 
-void
 Mixer_UI::show_window ()
 {
        if (_parent_window) {
@@ -1019,16 +995,16 @@ 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());
@@ -1848,63 +1824,24 @@ Mixer_UI::set_state (const XMLNode& node, int version)
 XMLNode&
 Mixer_UI::get_state ()
 {
-       XMLNode* node = new XMLNode ("Mixer");
-
-       if (_parent_window && _parent_window->is_realized() ) {
-               Glib::RefPtr<Gdk::Window> win = _parent_window->get_window();
+       XMLNode* node = new XMLNode (X_("Mixer"));
+       char buf[128];
 
-               get_window_pos_and_size ();
+       node->add_child_nocopy (Tabbable::get_state());
 
-               XMLNode* geometry = new XMLNode ("geometry");
-               char buf[32];
-               snprintf(buf, sizeof(buf), "%d", m_width);
-               geometry->add_property(X_("x_size"), string(buf));
-               snprintf(buf, sizeof(buf), "%d", m_height);
-               geometry->add_property(X_("y_size"), string(buf));
-               snprintf(buf, sizeof(buf), "%d", m_root_x);
-               geometry->add_property(X_("x_pos"), string(buf));
-               snprintf(buf, sizeof(buf), "%d", m_root_y);
-               geometry->add_property(X_("y_pos"), string(buf));
-
-               // written only for compatibility, they are not used.
-               snprintf(buf, sizeof(buf), "%d", 0);
-               geometry->add_property(X_("x_off"), string(buf));
-               snprintf(buf, sizeof(buf), "%d", 0);
-               geometry->add_property(X_("y_off"), string(buf));
-
-               snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane1)->gobj()));
-               geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
-               snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane2)->gobj()));
-               geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf));
-               snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&list_hpane)->gobj()));
-               geometry->add_property(X_("mixer_list_hpane_pos"), string(buf));
-
-               node->add_child_nocopy (*geometry);
-       }
+       snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (const_cast<GtkPaned*>(static_cast<const Paned*>(&rhs_pane1)->gobj())));
+       node->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
+       snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (const_cast<GtkPaned*>(static_cast<const Paned*>(&list_hpane)->gobj())));
+       node->add_property(X_("mixer_list_hpane_pos"), string(buf));
 
        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 ();
-       XMLNode* plugin_order = new XMLNode ("PluginOrder");
-       int cnt = 0;
-       for (PluginInfoList::const_iterator i = favorite_order.begin(); i != favorite_order.end(); ++i, ++cnt) {
-                       XMLNode* p = new XMLNode ("PluginInfo");
-                       p->add_property ("sort", cnt);
-                       p->add_property ("unique-id", (*i)->unique_id);
-                       if (favorite_ui_state.find ((*i)->unique_id) != favorite_ui_state.end ()) {
-                               p->add_property ("expanded", favorite_ui_state[(*i)->unique_id]);
-                       }
-                       plugin_order->add_child_nocopy (*p);
-               ;
-       }
-       node->add_child_nocopy (*plugin_order);
        return *node;
 }
 
-
 void
 Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which)
 {
@@ -2163,7 +2100,7 @@ Mixer_UI::update_title ()
        if (!own_window()) {
                return;
        }
-       
+
        if (_session) {
                string n;
 
index 4721bf106f81c75fd301b3ebffc384391452d20b..68c31757e59d9381756013c4fab4e00fff9e78b1 100644 (file)
@@ -81,7 +81,7 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
        static Mixer_UI* instance();
        ~Mixer_UI();
 
-       Gtk::Window* use_own_window ();
+       Gtk::Window* use_own_window (bool and_fill_it);
        void show_window ();
 
        void set_session (ARDOUR::Session *);
index fee9e4709407006e7bba921a2db26e041270f91a..1d78c8e855a154292d2b8b73be8035a9f20d4827 100644 (file)
@@ -3250,11 +3250,11 @@ RCOptionEditor::populate_sync_options ()
 }
 
 Gtk::Window*
-RCOptionEditor::use_own_window ()
+RCOptionEditor::use_own_window (bool and_fill_it)
 {
        bool new_window = !own_window();
        
-       Gtk::Window* win = Tabbable::use_own_window ();
+       Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
 
        if (win && new_window) {
                win->set_name ("PreferencesWindow");
index 1681a92a2bc7b85ed90dcb5f5ff745793e7ea066..416563dac5ff0681ba4ab97e24ee21b413f5b116 100644 (file)
@@ -41,7 +41,7 @@ public:
 
        void populate_sync_options ();
 
-       Gtk::Window* use_own_window ();
+       Gtk::Window* use_own_window (bool and_fill_it);
        
 private:
        void parameter_changed (std::string const &);
index 3ab742199d1ad44d51cb8ee4568ad3ddba073e16..e876668e59fc3c07a002e52f4dd0f1828694b66e 100644 (file)
@@ -115,15 +115,12 @@ Manager::add_state (XMLNode& root) const
        for (Windows::const_iterator i = _windows.begin(); i != _windows.end(); ++i) {
                /* don't save state for temporary proxy windows
                 */
+
                if (dynamic_cast<ProxyTemporary*> (*i)) {
                        continue;
                }
-               if (dynamic_cast<ProcessorWindowProxy*> (*i)) {
-                       ProcessorWindowProxy *pi = dynamic_cast<ProcessorWindowProxy*> (*i);
-                       root.add_child_nocopy (pi->get_state());
-               } else {
-                       root.add_child_nocopy ((*i)->get_state());
-               }
+
+               root.add_child_nocopy ((*i)->get_state());
        }
 }
 
index 7c7dd15d23dfecdb190c882a0052e81f592f090f..5ed0eeb843e786218565f2f5ed5d59a1d7b3a3fb 100644 (file)
@@ -46,8 +46,7 @@ class LIBGTKMM2EXT_API Tabbable : public WindowProxy {
        
        Gtk::Window* get (bool create = false);
        Gtk::Window* own_window () { return get (false); } 
-       Gtk::Notebook* tabbed_parent ();
-       virtual Gtk::Window* use_own_window ();
+       virtual Gtk::Window* use_own_window (bool and_pack_it);
 
        bool has_own_window () const;
        bool is_tabbed () const;
@@ -59,6 +58,11 @@ class LIBGTKMM2EXT_API Tabbable : public WindowProxy {
        Gtk::Window* current_toplevel () const;
 
        Gtk::Notebook* tab_root_drop ();
+
+       int set_state (const XMLNode&, int version);
+       XMLNode& get_state ();
+       
+       static std::string xml_node_name();
        
   protected:
        bool delete_event_handler (GdkEventAny *ev);
index 01f53826bd436cb900d5f614bbf3d7b6c1d55b37..a0026d9f970071b11cf2a165dce20f61506f2f42 100644 (file)
@@ -73,6 +73,8 @@ class LIBGTKMM2EXT_API WindowProxy : public PBD::StatefulDestructible, public vi
     
        operator bool() const { return _window != 0; }
     
+       static std::string xml_node_name();
+
   protected:
        std::string  _name;
        std::string  _menu_name;
index 45e21a6b7bc2d8998e0b329c03a789612d2c1a7e..245be5542fece9224e92b4688fc38700a23a2164 100644 (file)
@@ -24,6 +24,8 @@
 #include "gtkmm2ext/tabbable.h"
 #include "gtkmm2ext/visibility_tracker.h"
 
+#include "i18n.h"
+
 using namespace Gtkmm2ext;
 using namespace Gtk;
 using std::string;
@@ -55,9 +57,20 @@ Tabbable::add_to_notebook (Notebook& notebook, const string& tab_title, int posi
 }
 
 Window*
-Tabbable::use_own_window ()
+Tabbable::use_own_window (bool and_pack_it)
 {
-       return get (true);
+       Gtk::Window* win = get (true);
+
+       if (and_pack_it) {
+               Gtk::Container* parent = _contents.get_parent();
+               if (parent) {
+                       parent->remove (_contents);
+               }
+               _own_notebook.append_page (_contents, _tab_title);
+       }
+
+       return win;
+
 }
 
 bool
@@ -108,7 +121,7 @@ Tabbable::tab_root_drop ()
 
        alloc = _contents.get_parent()->get_allocation();
        
-       (void) use_own_window ();
+       (void) use_own_window (false);
        
        /* This is called after a drop of a tab onto the root window. Its
         * responsibility is to return the notebook that this Tabbable's
@@ -212,3 +225,33 @@ Tabbable::current_toplevel () const
 {
        return dynamic_cast<Gtk::Window*> (contents().get_toplevel());
 }
+
+string
+Tabbable::xml_node_name()
+{
+       return WindowProxy::xml_node_name();
+}
+
+XMLNode&
+Tabbable::get_state()
+{
+       XMLNode& node (WindowProxy::get_state());
+
+       return node;
+}
+
+int
+Tabbable::set_state (const XMLNode& node, int version)
+{
+       int ret;
+
+       if ((ret = WindowProxy::set_state (node, version)) == 0) {
+               if (_visible) {
+                       if (use_own_window (true) == 0) {
+                               ret = -1;
+                       }
+               }
+       }
+
+       return ret;
+}
index d393f4d9bb41f880d800669e448fe20ea1d36ac3..dd1d4c35bd3d13d7381c17e7d653addd8934b9e5 100644 (file)
@@ -171,10 +171,16 @@ WindowProxy::toggle()
        }
 }
 
+std::string
+WindowProxy::xml_node_name()
+{
+       return X_("Window");
+}
+
 XMLNode&
 WindowProxy::get_state ()
 {
-       XMLNode* node = new XMLNode (X_("Window"));
+       XMLNode* node = new XMLNode (xml_node_name());
        char buf[32];   
 
        node->add_property (X_("name"), _name);