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"
24 #include "pbd/stacktrace.h"
26 #include "gtkmm2ext/window_proxy.h"
27 #include "gtkmm2ext/visibility_tracker.h"
32 using namespace Gtkmm2ext;
35 WindowProxy::WindowProxy (const std::string& name)
44 , _state_mask (StateMask (Position|Size))
48 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name)
50 , _menu_name (menu_name)
58 , _state_mask (StateMask (Position|Size))
62 WindowProxy::WindowProxy (const std::string& name, const std::string& menu_name, const XMLNode& node)
64 , _menu_name (menu_name)
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 ()
214 delete_connection.disconnect ();
215 configure_connection.disconnect ();
216 map_connection.disconnect ();
217 unmap_connection.disconnect ();
227 WindowProxy::use_window (Gtk::Window& win)
235 WindowProxy::setup ()
239 vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
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 /* 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)