2 * Copyright (C) 2015-2018 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2017-2018 Robin Gareus <robin@gareus.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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()) {
149 vistracker->cycle_visibility ();
154 if (_window->is_mapped()) {
155 if (_width != -1 && _height != -1) {
156 _window->set_default_size (_width, _height);
158 if (_x_off != -1 && _y_off != -1) {
159 _window->move (_x_off, _y_off);
166 WindowProxy::xml_node_name()
172 WindowProxy::get_state ()
174 XMLNode* node = new XMLNode (xml_node_name());
176 node->set_property (X_("name"), _name);
178 if (_window && vistracker) {
180 /* we have a window, so use current state */
182 _visible = vistracker->partially_visible ();
183 _window->get_position (_x_off, _y_off);
184 _window->get_size (_width, _height);
189 if (_state_mask & Position) {
197 if (_state_mask & Size) {
205 node->set_property (X_("visible"), _visible);
206 node->set_property (X_("x-off"), x);
207 node->set_property (X_("y-off"), y);
208 node->set_property (X_("x-size"), w);
209 node->set_property (X_("y-size"), h);
215 WindowProxy::drop_window ()
219 delete_connection.disconnect ();
220 configure_connection.disconnect ();
221 map_connection.disconnect ();
222 unmap_connection.disconnect ();
231 WindowProxy::use_window (Gtk::Window& win)
239 WindowProxy::setup ()
245 delete_connection = _window->signal_delete_event().connect (sigc::mem_fun (*this, &WindowProxy::delete_event_handler));
246 configure_connection = _window->signal_configure_event().connect (sigc::mem_fun (*this, &WindowProxy::configure_handler), false);
247 map_connection = _window->signal_map().connect (sigc::mem_fun (*this, &WindowProxy::map_handler), false);
248 unmap_connection = _window->signal_unmap().connect (sigc::mem_fun (*this, &WindowProxy::unmap_handler), false);
254 WindowProxy::map_handler ()
256 vistracker = new Gtkmm2ext::VisibilityTracker (*_window);
257 /* emit our own signal */
262 WindowProxy::unmap_handler ()
264 /* emit out own signal */
269 WindowProxy::configure_handler (GdkEventConfigure* ev)
271 /* stupidly, the geometry data in the event isn't the same as we get
272 from the window geometry APIs.so we have to actively interrogate
273 them to get the new information.
275 the difference is generally down to window manager framing.
277 if (!visible() || !_window->is_mapped()) {
280 save_pos_and_size ();
286 WindowProxy::visible() const
289 /* update with current state */
290 _visible = vistracker->partially_visible();
296 WindowProxy::fully_visible () const
299 /* no vistracker .. no window .. cannot be fully visible */
302 return vistracker->fully_visible();
314 WindowProxy::maybe_show ()
322 WindowProxy::show_all ()
326 _window->show_all ();
330 WindowProxy::present ()
335 _window->show_all ();
338 /* turn off any mouse-based positioning */
339 _window->set_position (Gtk::WIN_POS_NONE);
352 WindowProxy::delete_event_handler (GdkEventAny* /*ev*/)
355 _action->activate ();
364 WindowProxy::save_pos_and_size ()
367 _window->get_position (_x_off, _y_off);
368 _window->get_size (_width, _height);
373 WindowProxy::set_pos_and_size ()
379 if ((_state_mask & Position) && (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1)) {
380 /* cancel any mouse-based positioning */
381 _window->set_position (Gtk::WIN_POS_NONE);
384 if ((_state_mask & Size) && _width != -1 && _height != -1) {
385 _window->resize (_width, _height);
388 if ((_state_mask & Position) && _x_off != -1 && _y_off != -1) {
389 _window->move (_x_off, _y_off);
394 WindowProxy::set_pos ()
400 if (!(_state_mask & Position)) {
404 if (_width != -1 || _height != -1 || _x_off != -1 || _y_off != -1) {
405 /* cancel any mouse-based positioning */
406 _window->set_position (Gtk::WIN_POS_NONE);
409 if (_x_off != -1 && _y_off != -1) {
410 _window->move (_x_off, _y_off);
415 WindowProxy::set_state_mask (StateMask sm)