--- a/src/join-views.cpp +++ b/src/join-views.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -5,41 +7,62 @@ class JoinViewsSingleton { + /* One geometry-changed connection per mapped view, so every parent keeps + * positioning its children -- not just the most recently mapped view. */ + using geometry_conn_t = wf::signal::connection_t; + std::map> geometry_conns; + + void reposition_children(wayfire_toplevel_view view) + { + if (!view || !view->is_mapped()) + { + return; + } + + auto parent_geometry = view->get_pending_geometry(); + int cx = parent_geometry.x + parent_geometry.width / 2; + int cy = parent_geometry.y + parent_geometry.height / 2; + for (auto child : view->children) + { + auto target = child->get_pending_geometry(); + target.x = cx - target.width / 2; + target.y = cy - target.height / 2; + child->set_geometry(target); + } + } + public: - wf::signal::connection_t on_geometry_changed{[= - ] (wf::view_geometry_changed_signal *ev) + wf::signal::connection_t on_view_map{[=] (wf::view_mapped_signal *ev) { - auto view = wf::toplevel_cast(ev->view); - if (!view || !view->is_mapped()) + auto view = ev->view; + if (!view || geometry_conns.count(view.get())) { return; } - auto parent_geometry = view->get_pending_geometry(); - int cx = parent_geometry.x + parent_geometry.width / 2; - int cy = parent_geometry.y + parent_geometry.height / 2; - for (auto child : view->children) + auto conn = std::make_shared( + [=] (wf::view_geometry_changed_signal *gev) { - auto target = child->get_pending_geometry(); - target.x = cx - target.width / 2; - target.y = cy - target.height / 2; - child->set_geometry(target); - } + reposition_children(gev->view); + }); + view->connect(conn.get()); + geometry_conns[view.get()] = conn; } }; - wf::signal::connection_t on_view_map{[=] (wf::view_mapped_signal *ev) + wf::signal::connection_t on_view_unmap{[=] (wf::view_unmapped_signal *ev) { - auto view = ev->view; - /* Make sure only a single connection is made */ - on_geometry_changed.disconnect(); - view->connect(&on_geometry_changed); + if (ev->view) + { + geometry_conns.erase(ev->view.get()); + } } }; void handle_new_output(wf::output_t *output) { output->connect(&on_view_map); + output->connect(&on_view_unmap); } JoinViewsSingleton()