2 Copyright (C) 2015 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gtkmm/action.h>
21 #include <gtkmm/window.h>
23 #include "pbd/xml++.h"
25 #include "gtkmm2ext/window_proxy.h"
26 #include "gtkmm2ext/visibility_tracker.h"
31 using namespace Gtkmm2ext;
34 WindowProxy::WindowProxy (const std::string& name)
43 , _state_mask (StateMask (Position|Size))
47 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name)
49 , _menu_name (menu_name)
57 , _state_mask (StateMask (Position|Size))
61 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode& node)
63 , _menu_name (menu_name)
71 , _state_mask (StateMask (Position|Size))
76 WindowProxy::~WindowProxy ()
83 WindowProxy::set_state (const XMLNode& node, int /* version */)
85 XMLNodeList children = node.children ();
86 XMLNode const * child;
87 XMLNodeList::const_iterator i = children.begin ();
89 while (i != children.end()) {
92 if (child->name () == X_("Window") && child->get_property (X_("name"), name) &&
100 if (i != children.end()) {
104 child->get_property (X_("visible"), _visible);
105 child->get_property (X_("x-off"), _x_off);
106 child->get_property (X_("y-off"), _y_off);
107 child->get_property (X_("x-size"), _width);
108 child->get_property (X_("y-size"), _height);
119 WindowProxy::set_action (Glib::RefPtr<Gtk::Action> act)
125 WindowProxy::action_name() const
127 return string_compose (X_("toggle-%1"), _name);
131 WindowProxy::toggle()
137 /* XXX this is a hack - the window object should really
138 ensure its components are all visible. sigh.
141 /* we'd like to just call this and nothing else */
144 if (_window->is_mapped()) {
148 vistracker->cycle_visibility ();
150 if (_window->is_mapped()) {
151 if (_width != -1 && _height != -1) {
152 _window->set_default_size (_width, _height);
154 if (_x_off != -1 && _y_off != -1) {
155 _window->move (_x_off, _y_off);
162 WindowProxy::xml_node_name()
168 WindowProxy::get_state ()
170 XMLNode* node = new XMLNode (xml_node_name());
172 node->set_property (X_("name"), _name);
174 if (_window && vistracker) {
176 /* we have a window, so use current state */
178 _visible = vistracker->partially_visible ();
179 _window->get_position (_x_off, _y_off);
180 _window->get_size (_width, _height);
185 if (_state_mask & Position) {
193 if (_state_mask & Size) {
201 node->set_property (X_("visible"), _visible);
202 node->set_property (X_("x-off"), x);
203 node->set_property (X_("y-off"), y);
204 node->set_property (X_("x-size"), w);
205 node->set_property (X_("y-size"), h);
211 WindowProxy::drop_window ()
215 delete_connection.disconnect ();
216 configure_connection.disconnect ();
217 map_connection.disconnect ();
218 unmap_connection.disconnect ();
227 WindowProxy::use_window (Gtk::Window& win)
235 WindowProxy::setup ()
241 delete_connection = _window->signal_delete_event().connect (sigc::mem_fun (*this, &WindowProxy::delete_event_handler));
242 configure_connection = _window->signal_configure_event().connect (sigc::mem_fun (*this, &WindowProxy::configure_handler), false);
243 map_connection = _window->signal_map().connect (sigc::mem_fun (*this, &WindowProxy::map_handler), false);
244 unmap_connection = _window->signal_unmap().connect (sigc::mem_fun (*this, &WindowProxy::unmap_handler), false);
250 WindowProxy::map_handler ()
252 vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
253 /* emit our own signal */
258 WindowProxy::unmap_handler ()
260 /* emit out own signal */
265 WindowProxy::configure_handler (GdkEventConfigure* ev)
267 /* stupidly, the geometry data in the event isn't the same as we get
268 from the window geometry APIs.so we have to actively interrogate
269 them to get the new information.
271 the difference is generally down to window manager framing.
273 if (!visible() || !_window->is_mapped()) {
276 save_pos_and_size ();
282 WindowProxy::visible() const
285 /* update with current state */
286 _visible = vistracker->partially_visible();
292 WindowProxy::fully_visible () const
295 /* no vistracker .. no window .. cannot be fully visible */
298 return vistracker->fully_visible();
310 WindowProxy::maybe_show ()
318 WindowProxy::show_all ()
322 _window->show_all ();
326 WindowProxy::present ()
331 _window->show_all ();
334 /* turn off any mouse-based positioning */
335 _window->set_position (Gtk::WIN_POS_NONE);
348 WindowProxy::delete_event_handler (GdkEventAny* /*ev*/)
351 _action->activate ();
360 WindowProxy::save_pos_and_size ()
363 _window->get_position (_x_off, _y_off);
364 _window->get_size (_width, _height);
369 WindowProxy::set_pos_and_size ()
375 if ((_state_mask & Position) && (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1)) {
376 /* cancel any mouse-based positioning */
377 _window->set_position (Gtk::WIN_POS_NONE);
380 if ((_state_mask & Size) && _width != -1 && _height != -1) {
381 _window->resize (_width, _height);
384 if ((_state_mask & Position) && _x_off != -1 && _y_off != -1) {
385 _window->move (_x_off, _y_off);
390 WindowProxy::set_pos ()
396 if (!(_state_mask & Position)) {
400 if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
401 /* cancel any mouse-based positioning */
402 _window->set_position (Gtk::WIN_POS_NONE);
405 if (_x_off != -1 && _y_off != -1) {
406 _window->move (_x_off, _y_off);
411 WindowProxy::set_state_mask (StateMask sm)