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)
75 WindowProxy::~WindowProxy ()
82 WindowProxy::set_state (const XMLNode& node, int /* version */)
84 XMLNodeList children = node.children ();
85 XMLNode const * child;
86 XMLNodeList::const_iterator i = children.begin ();
88 while (i != children.end()) {
91 if (child->name () == X_("Window") && child->get_property (X_("name"), name) &&
99 if (i != children.end()) {
103 child->get_property (X_("visible"), _visible);
104 child->get_property (X_("x-off"), _x_off);
105 child->get_property (X_("y-off"), _y_off);
106 child->get_property (X_("x-size"), _width);
107 child->get_property (X_("y-size"), _height);
118 WindowProxy::set_action (Glib::RefPtr<Gtk::Action> act)
124 WindowProxy::action_name() const
126 return string_compose (X_("toggle-%1"), _name);
130 WindowProxy::toggle()
136 /* XXX this is a hack - the window object should really
137 ensure its components are all visible. sigh.
140 /* we'd like to just call this and nothing else */
143 if (_window->is_mapped()) {
147 vistracker->cycle_visibility ();
149 if (_window->is_mapped()) {
150 if (_width != -1 && _height != -1) {
151 _window->set_default_size (_width, _height);
153 if (_x_off != -1 && _y_off != -1) {
154 _window->move (_x_off, _y_off);
161 WindowProxy::xml_node_name()
167 WindowProxy::get_state ()
169 XMLNode* node = new XMLNode (xml_node_name());
171 node->set_property (X_("name"), _name);
173 if (_window && vistracker) {
175 /* we have a window, so use current state */
177 _visible = vistracker->partially_visible ();
178 _window->get_position (_x_off, _y_off);
179 _window->get_size (_width, _height);
184 if (_state_mask & Position) {
192 if (_state_mask & Size) {
200 node->set_property (X_("visible"), _visible);
201 node->set_property (X_("x-off"), x);
202 node->set_property (X_("y-off"), y);
203 node->set_property (X_("x-size"), w);
204 node->set_property (X_("y-size"), h);
210 WindowProxy::drop_window ()
213 delete_connection.disconnect ();
214 configure_connection.disconnect ();
215 map_connection.disconnect ();
216 unmap_connection.disconnect ();
226 WindowProxy::use_window (Gtk::Window& win)
234 WindowProxy::setup ()
240 delete_connection = _window->signal_delete_event().connect (sigc::mem_fun (*this, &WindowProxy::delete_event_handler));
241 configure_connection = _window->signal_configure_event().connect (sigc::mem_fun (*this, &WindowProxy::configure_handler), false);
242 map_connection = _window->signal_map().connect (sigc::mem_fun (*this, &WindowProxy::map_handler), false);
243 unmap_connection = _window->signal_unmap().connect (sigc::mem_fun (*this, &WindowProxy::unmap_handler), false);
249 WindowProxy::map_handler ()
251 vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
252 /* emit our own signal */
257 WindowProxy::unmap_handler ()
259 /* emit out own signal */
264 WindowProxy::configure_handler (GdkEventConfigure* ev)
266 /* stupidly, the geometry data in the event isn't the same as we get
267 from the window geometry APIs.so we have to actively interrogate
268 them to get the new information.
270 the difference is generally down to window manager framing.
272 if (!visible() || !_window->is_mapped()) {
275 save_pos_and_size ();
281 WindowProxy::visible() const
284 /* update with current state */
285 _visible = vistracker->partially_visible();
291 WindowProxy::fully_visible () const
294 /* no vistracker .. no window .. cannot be fully visible */
297 return vistracker->fully_visible();
309 WindowProxy::maybe_show ()
317 WindowProxy::show_all ()
321 _window->show_all ();
325 WindowProxy::present ()
330 _window->show_all ();
333 /* turn off any mouse-based positioning */
334 _window->set_position (Gtk::WIN_POS_NONE);
347 WindowProxy::delete_event_handler (GdkEventAny* /*ev*/)
350 _action->activate ();
359 WindowProxy::save_pos_and_size ()
362 _window->get_position (_x_off, _y_off);
363 _window->get_size (_width, _height);
368 WindowProxy::set_pos_and_size ()
374 if ((_state_mask & Position) && (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1)) {
375 /* cancel any mouse-based positioning */
376 _window->set_position (Gtk::WIN_POS_NONE);
379 if ((_state_mask & Size) && _width != -1 && _height != -1) {
380 _window->resize (_width, _height);
383 if ((_state_mask & Position) && _x_off != -1 && _y_off != -1) {
384 _window->move (_x_off, _y_off);
389 WindowProxy::set_pos ()
395 if (!(_state_mask & Position)) {
399 if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
400 /* cancel any mouse-based positioning */
401 _window->set_position (Gtk::WIN_POS_NONE);
404 if (_x_off != -1 && _y_off != -1) {
405 _window->move (_x_off, _y_off);
410 WindowProxy::set_state_mask (StateMask sm)