diff --git a/plugins/animate/animate.cpp b/plugins/animate/animate.cpp index b1ffdf961..d29650c48 100644 --- a/plugins/animate/animate.cpp +++ b/plugins/animate/animate.cpp @@ -16,6 +16,7 @@ #include "wayfire/scene-operations.hpp" #include "wayfire/scene.hpp" #include "wayfire/signal-provider.hpp" +#include "wayfire/view.hpp" #include void animation_base::init(wayfire_view, int, wf_animation_type) @@ -67,8 +68,8 @@ struct animation_hook : public animation_hook_base static_assert(std::is_base_of::value, "animation_type must be derived from animation_base!"); + std::shared_ptr view; wf_animation_type type; - wayfire_view view; std::string name; wf::output_t *current_output = nullptr; std::unique_ptr animation; @@ -125,7 +126,7 @@ struct animation_hook : public animation_hook_base std::string name) { this->type = type; - this->view = view; + this->view = view->shared_from_this(); this->name = name; animation = std::make_unique(); @@ -135,10 +136,7 @@ struct animation_hook : public animation_hook_base /* Animation is driven by the output render cycle the view is on. * Thus, we need to keep in sync with the current output. */ view->connect(&on_set_output); - - // Take a ref on the view, so that it remains available for as long as the animation runs. wf::scene::set_node_enabled(view->get_root_node(), true); - view->take_ref(); if (type == ANIMATION_TYPE_UNMAP) { @@ -216,7 +214,6 @@ struct animation_hook : public animation_hook_base unset_unmapped_contents(); wf::scene::set_node_enabled(view->get_root_node(), false); - view->unref(); } animation_hook(const animation_hook &) = delete; diff --git a/plugins/single_plugins/move.cpp b/plugins/single_plugins/move.cpp index 8d0aa98ae..0c66a507f 100644 --- a/plugins/single_plugins/move.cpp +++ b/plugins/single_plugins/move.cpp @@ -1,6 +1,7 @@ #include "wayfire/debug.hpp" #include "wayfire/geometry.hpp" #include "wayfire/plugins/common/input-grab.hpp" +#include "wayfire/nonstd/tracking-allocator.hpp" #include "wayfire/scene-input.hpp" #include "wayfire/signal-provider.hpp" #include "wayfire/view-helpers.hpp" @@ -44,7 +45,7 @@ class wayfire_move : public wf::per_output_plugin_instance_t, struct { - nonstd::observer_ptr preview; + std::shared_ptr preview; wf::grid::slot_t slot_id = wf::grid::SLOT_NONE; } slot; @@ -485,14 +486,12 @@ class wayfire_move : public wf::per_output_plugin_instance_t, } auto input = get_input_coords(); - auto preview = - new wf::preview_indication_view_t({input.x, input.y, 1, 1}, "move"); - wf::get_core().add_view( - std::unique_ptr(preview)); - preview->set_output(output); - - preview->set_target_geometry(slot_geometry, 1); - slot.preview = nonstd::make_observer(preview); + slot.preview = wf::tracking_allocator_t::get() + .allocate(wf::geometry_t{input.x, input.y, 1, 1}, "move"); + + wf::view_interface_t::initialize_new(slot.preview); + slot.preview->set_output(output); + slot.preview->set_target_geometry(slot_geometry, 1); } update_workspace_switch_timeout(new_slot_id); diff --git a/plugins/tile/tree-controller.cpp b/plugins/tile/tree-controller.cpp index 36745a09b..ce6e927ab 100644 --- a/plugins/tile/tree-controller.cpp +++ b/plugins/tile/tree-controller.cpp @@ -1,6 +1,7 @@ #include "tree-controller.hpp" #include +#include #include #include #include @@ -242,11 +243,10 @@ void move_view_controller_t::ensure_preview(wf::point_t start) return; } - auto view = - std::make_unique(start, "simple-tile"); - this->preview = {view}; - wf::get_core().add_view(std::move(view)); - this->preview->set_output(output); + preview = wf::tracking_allocator_t::get() + .allocate(start, "simple-tile"); + wf::view_interface_t::initialize_new(preview); + preview->set_output(output); } void move_view_controller_t::input_motion(wf::point_t input) diff --git a/plugins/tile/tree-controller.hpp b/plugins/tile/tree-controller.hpp index 46b300448..aefdc840c 100644 --- a/plugins/tile/tree-controller.hpp +++ b/plugins/tile/tree-controller.hpp @@ -91,7 +91,7 @@ class move_view_controller_t : public tile_controller_t wf::output_t *output; wf::point_t current_input; - nonstd::observer_ptr preview; + std::shared_ptr preview; /** * Create preview if it doesn't exist * diff --git a/src/api/wayfire/core.hpp b/src/api/wayfire/core.hpp index 8f7068716..1658c0977 100644 --- a/src/api/wayfire/core.hpp +++ b/src/api/wayfire/core.hpp @@ -250,17 +250,12 @@ class compositor_core_t : public wf::object_base_t, public signal::provider_t nonstd::observer_ptr gesture) = 0; /** - * Add a view to the compositor's view list. The view will be freed when - * its keep_count drops to zero, hence a plugin using this doesn't have to - * erase the view manually (instead it should just drop the keep_count) - */ - virtual void add_view(std::unique_ptr view) = 0; - - /** + * @deprecated. Use tracking_allocator_t::get_all() + * * @return A list of all views core manages, regardless of their output, * properties, etc. */ - virtual std::vector get_all_views() = 0; + std::vector get_all_views(); /** * Focus the given output. The currently focused output is used to determine diff --git a/src/api/wayfire/nonstd/observer_ptr.h b/src/api/wayfire/nonstd/observer_ptr.h index cd38e51fe..bb67b3a07 100644 --- a/src/api/wayfire/nonstd/observer_ptr.h +++ b/src/api/wayfire/nonstd/observer_ptr.h @@ -155,6 +155,10 @@ class observer_ptr nop_constexpr14 observer_ptr(const std::unique_ptr& other) : ptr(other.get()) {} + template< class W2 > + nop_constexpr14 observer_ptr(const std::shared_ptr& other) + : ptr(other.get()) {} + nop_constexpr14 pointer get() const nop_noexcept { return ptr; diff --git a/src/api/wayfire/signal-definitions.hpp b/src/api/wayfire/signal-definitions.hpp index 647b20764..14d1b0742 100644 --- a/src/api/wayfire/signal-definitions.hpp +++ b/src/api/wayfire/signal-definitions.hpp @@ -358,15 +358,6 @@ struct fullscreen_layer_focused_signal /* ----------------------------------------------------------------------------/ * View signals * -------------------------------------------------------------------------- */ -/** - * on: core - * when: A view is created. - */ -struct view_added_signal -{ - wayfire_view view; -}; - /** * on: view, output, core * when: After the view becomes mapped. This signal must also be emitted from all compositor views. diff --git a/src/api/wayfire/toplevel-view.hpp b/src/api/wayfire/toplevel-view.hpp index 851fbdd9e..ef0fc5512 100644 --- a/src/api/wayfire/toplevel-view.hpp +++ b/src/api/wayfire/toplevel-view.hpp @@ -187,6 +187,16 @@ class toplevel_view_interface_t : public wf::view_interface_t virtual ~toplevel_view_interface_t(); + std::shared_ptr shared_from_this() + { + return std::dynamic_pointer_cast(view_interface_t::shared_from_this()); + } + + std::weak_ptr weak_from_this() + { + return shared_from_this(); + } + protected: /** * When a view is being destroyed, all associated objects like subsurfaces, diff --git a/src/api/wayfire/view.hpp b/src/api/wayfire/view.hpp index 719433cfb..83b827ef1 100644 --- a/src/api/wayfire/view.hpp +++ b/src/api/wayfire/view.hpp @@ -33,12 +33,6 @@ namespace scene class view_node_t; } -// A signal emitted when the view is destroyed and its memory will be freed. -struct view_destruct_signal -{ - wayfire_view view; -}; - /* abstraction for desktop-apis, no real need for plugins * This is a base class to all "drawables" - desktop views, subsurfaces, popups */ enum view_role_t @@ -55,10 +49,19 @@ enum view_role_t }; /** - * view_interface_t is the base class for all "toplevel windows", i.e surfaces - * which have no parent. + * The view_interface_t represents a window shown to the user. It includes panels, backgrounds, notifications, + * and toplevels (which derive from the subclass toplevel_view_interface_t). + * + * Views should be allocated via the helper allocator tracking_allocator_t: + * ``` + * auto& alloc = tracking_allocator_t::get(); + * alloc.allocate(arguments) + * ``` + * + * This ensures that all plugins can query a list of all available views at any given time. */ -class view_interface_t : public wf::signal::provider_t, public wf::object_base_t +class view_interface_t : public wf::signal::provider_t, public wf::object_base_t, + public std::enable_shared_from_this { public: /** @@ -164,19 +167,6 @@ class view_interface_t : public wf::signal::provider_t, public wf::object_base_t */ virtual void take_snapshot(wf::render_target_t& target); - /** - * View lifetime is managed by reference counting. To take a reference, - * use take_ref(). Note that one reference is automatically made when the - * view is created. - */ - void take_ref(); - - /** - * Drop a reference to the surface. When the reference count reaches 0, the - * destruct() method is called. - */ - void unref(); - /** * @return the wl_client associated with this surface, or null if the * surface doesn't have a backing wlr_surface. @@ -197,6 +187,7 @@ class view_interface_t : public wf::signal::provider_t, public wf::object_base_t class view_priv_impl; std::unique_ptr priv; + static void initialize_new(wayfire_view view); protected: view_interface_t(); @@ -226,13 +217,6 @@ class view_interface_t : public wf::signal::provider_t, public wf::object_base_t */ virtual void deinitialize(); - /** - * Called when the reference count reaches 0. - * It destructs the object and deletes it, so "this" may not be - * accessed after destruct() is called. - */ - virtual void destruct(); - /** * Emit the view map signal. It indicates that a view has been mapped, i.e. * plugins can now "work" with it. Note that not all views will emit the map diff --git a/src/core/core-impl.hpp b/src/core/core-impl.hpp index 0107a768b..dc6bb4db7 100644 --- a/src/core/core-impl.hpp +++ b/src/core/core-impl.hpp @@ -38,18 +38,6 @@ class compositor_core_impl_t : public compositor_core_t */ virtual void post_init(); - /** - * Remove a view from the compositor list. This is called when the view's - * keep_count reaches zero for the first time after its creation. - */ - virtual void erase_view(wayfire_view view); - - /** - * Find a view by its stringified ID. - * @return nullptr if no such view exists. - */ - virtual wayfire_view find_view(const std::string& id); - static compositor_core_impl_t& get(); wlr_seat *get_current_seat() override; @@ -75,8 +63,6 @@ class compositor_core_impl_t : public compositor_core_t override; virtual wlr_cursor *get_wlr_cursor() override; - void add_view(std::unique_ptr view) override; - std::vector get_all_views() override; void focus_output(wf::output_t *o) override; wf::output_t *get_active_output() override; std::string get_xwayland_display() override; @@ -94,9 +80,6 @@ class compositor_core_impl_t : public compositor_core_t wf::wl_listener_wrapper idle_inhibitor_created; wf::output_t *active_output = nullptr; - std::vector> views; - std::unordered_map id_to_view; - std::shared_ptr scene_root; compositor_state_t state = compositor_state_t::UNKNOWN; diff --git a/src/core/core.cpp b/src/core/core.cpp index 2ed9b9035..594c43316 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -4,6 +4,7 @@ #include "wayfire/core.hpp" #endif +#include #include "wayfire/scene.hpp" #include #include "wayfire/scene-operations.hpp" @@ -397,68 +398,9 @@ wf::output_t*wf::compositor_core_impl_t::get_active_output() return active_output; } -void wf::compositor_core_impl_t::add_view( - std::unique_ptr view) +std::vector wf::compositor_core_t::get_all_views() { - auto v = view->self(); /* non-owning copy */ - views.push_back(std::move(view)); - id_to_view[std::to_string(v->get_id())] = v; - - assert(active_output); - - v->initialize(); - if (!v->get_output()) - { - v->set_output(active_output); - } - - view_added_signal data; - data.view = v; - emit(&data); -} - -std::vector wf::compositor_core_impl_t::get_all_views() -{ - std::vector result; - for (auto& view : this->views) - { - result.push_back({view}); - } - - return result; -} - -void wf::compositor_core_impl_t::erase_view(wayfire_view v) -{ - if (!v) - { - return; - } - - if (v->get_output()) - { - v->set_output(nullptr); - } - - wf::scene::remove_child(v->get_root_node()); - auto it = std::find_if(views.begin(), views.end(), - [&v] (const auto& view) { return view.get() == v.get(); }); - - v->deinitialize(); - - id_to_view.erase(std::to_string(v->get_id())); - views.erase(it); -} - -wayfire_view wf::compositor_core_impl_t::find_view(const std::string& id) -{ - auto it = id_to_view.find(id); - if (it != id_to_view.end()) - { - return it->second; - } - - return nullptr; + return wf::tracking_allocator_t::get().get_all(); } pid_t wf::compositor_core_impl_t::run(std::string command) @@ -594,9 +536,6 @@ wf::compositor_core_impl_t::compositor_core_impl_t() {} wf::compositor_core_impl_t::~compositor_core_impl_t() { - /* Unloading order is important. First we want to free any remaining views, - * then we destroy the input manager, and finally the rest is auto-freed */ - views.clear(); input.reset(); output_layout.reset(); } diff --git a/src/core/output-layout.cpp b/src/core/output-layout.cpp index e84ec3817..10a746070 100644 --- a/src/core/output-layout.cpp +++ b/src/core/output-layout.cpp @@ -2,6 +2,7 @@ #include "wayfire/core.hpp" #include "wayfire/output-layout.hpp" #include "wayfire/view-helpers.hpp" +#include "wayfire/view.hpp" #include "wayfire/workspace-set.hpp" #include "wayfire/render-manager.hpp" #include "wayfire/signal-definitions.hpp" @@ -157,14 +158,13 @@ void transfer_views(wf::output_t *from, wf::output_t *to) // Step 2: Ensure none of the remaining views have an invalid output. // Note that all views in workspace sets will have their output reassigned automatically by the // workspace-set impl. - std::vector non_ws_views; + std::vector> non_ws_views; for (auto& view : wf::get_core().get_all_views()) { if ((view->get_output() == from) && (!toplevel_cast(view) || !toplevel_cast(view)->get_wset())) { - non_ws_views.push_back(view); // Take a ref, so that the view doesn't get destroyed while we're doing operations on the views - view->take_ref(); + non_ws_views.push_back(view->shared_from_this()); } } @@ -181,12 +181,6 @@ void transfer_views(wf::output_t *from, wf::output_t *to) view->set_output(to); } } - - // Drop refs we have taken - for (auto& view : non_ws_views) - { - view->unref(); - } } bool output_state_t::operator ==(const output_state_t& other) const diff --git a/src/output/workspace-impl.cpp b/src/output/workspace-impl.cpp index f9f11f698..2e60f368e 100644 --- a/src/output/workspace-impl.cpp +++ b/src/output/workspace-impl.cpp @@ -17,6 +17,7 @@ #include "../view/view-impl.hpp" #include "wayfire/debug.hpp" #include "wayfire/geometry.hpp" +#include "wayfire/nonstd/tracking-allocator.hpp" #include "wayfire/option-wrapper.hpp" #include "wayfire/scene-input.hpp" #include "wayfire/scene.hpp" @@ -274,9 +275,10 @@ struct workspace_set_t::impl } }; - wf::signal::connection_t on_view_destruct = [=] (view_destruct_signal *ev) + wf::signal::connection_t> on_view_destruct = + [=] (wf::destruct_signal *ev) { - remove_view(toplevel_cast(ev->view)); + remove_view(toplevel_cast(ev->object)); }; bool visible = false; diff --git a/src/view/compositor-view.cpp b/src/view/compositor-view.cpp index e3e8a3f1d..dac0a5950 100644 --- a/src/view/compositor-view.cpp +++ b/src/view/compositor-view.cpp @@ -28,15 +28,16 @@ class wf::color_rect_view_t::color_rect_node_t : public wf::scene::floating_inne using simple_render_instance_t::simple_render_instance_t; void render(const wf::render_target_t& target, const wf::region_t& region) override { - if (!self->view) + auto view = self->_view.lock(); + if (!view) { return; } auto geometry = self->get_bounding_box(); - auto border = self->view->border; - auto _border_color = self->view->_border_color; - auto _color = self->view->_color; + auto border = view->border; + auto _border_color = view->_border_color; + auto _color = view->_color; OpenGL::render_begin(target); for (const auto& box : region) @@ -67,17 +68,12 @@ class wf::color_rect_view_t::color_rect_node_t : public wf::scene::floating_inne } }; - color_rect_view_t *view; - wf::signal::connection_t on_view_destroy = [=] (view_destruct_signal*) - { - view = nullptr; - }; + std::weak_ptr _view; public: color_rect_node_t(color_rect_view_t *view) : scene::floating_inner_node_t(false) { - this->view = view; - view->connect(&on_view_destroy); + _view = std::dynamic_pointer_cast(view->shared_from_this()); } void gen_render_instances(std::vector& instances, @@ -88,7 +84,7 @@ class wf::color_rect_view_t::color_rect_node_t : public wf::scene::floating_inne wf::geometry_t get_bounding_box() override { - if (view) + if (auto view = _view.lock()) { return view->get_geometry(); } else @@ -111,9 +107,7 @@ wf::color_rect_view_t::color_rect_view_t() : wf::view_interface_t() void wf::color_rect_view_t::close() { this->_is_mapped = false; - emit_view_unmap(); - unref(); } void wf::color_rect_view_t::set_color(wf::color_t color) diff --git a/src/view/layer-shell/layer-shell-node.cpp b/src/view/layer-shell/layer-shell-node.cpp index f8b1e4141..816c2aa27 100644 --- a/src/view/layer-shell/layer-shell-node.cpp +++ b/src/view/layer-shell/layer-shell-node.cpp @@ -10,21 +10,21 @@ wf::layer_shell_node_t::layer_shell_node_t(wayfire_view view) : view_node_tag_t(view) { this->kb_interaction = std::make_unique(view); - on_view_destroy = [=] (view_destruct_signal *ev) - { - this->view = nullptr; - this->kb_interaction = std::make_unique(); - }; - - view->connect(&on_view_destroy); - this->view = view; + this->_view = view->weak_from_this(); } std::string wf::layer_shell_node_t::stringify() const { - std::ostringstream out; - out << this->view; - return out.str() + " " + stringify_flags(); + auto view = _view.lock(); + if (view) + { + std::ostringstream out; + out << view->self(); + return out.str() + " " + stringify_flags(); + } else + { + return "inert layer-shell"; + } } wf::keyboard_interaction_t& wf::layer_shell_node_t::keyboard_interaction() @@ -34,6 +34,7 @@ wf::keyboard_interaction_t& wf::layer_shell_node_t::keyboard_interaction() wf::keyboard_focus_node_t wf::layer_shell_node_t::keyboard_refocus(wf::output_t *output) { + auto view = _view.lock(); if (!view || !view->get_keyboard_focus_surface()) { return wf::keyboard_focus_node_t{}; @@ -81,6 +82,7 @@ wf::keyboard_focus_node_t wf::layer_shell_node_t::keyboard_refocus(wf::output_t wf::region_t wf::layer_shell_node_t::get_opaque_region() const { + auto view = _view.lock(); if (view && view->is_mapped() && view->get_wlr_surface()) { auto surf = view->get_wlr_surface(); @@ -95,6 +97,7 @@ wf::region_t wf::layer_shell_node_t::get_opaque_region() const std::optional wf::layer_shell_node_t::to_texture() const { + auto view = _view.lock(); if (!view || !view->is_mapped() || (get_children().size() != 1)) { return {}; @@ -191,13 +194,14 @@ class layer_shell_render_instance_t : public wf::scene::translation_node_instanc void wf::layer_shell_node_t::gen_render_instances(std::vector & instances, scene::damage_callback push_damage, wf::output_t *shown_on) { + auto view = _view.lock(); if (!view) { return; } // Special case: layer-shell views live only inside their outputs and should not be shown on other outputs - if (shown_on && (this->view->get_output() != shown_on)) + if (shown_on && (view->get_output() != shown_on)) { return; } diff --git a/src/view/layer-shell/layer-shell-node.hpp b/src/view/layer-shell/layer-shell-node.hpp index ec5cd329e..c69c4a5b9 100644 --- a/src/view/layer-shell/layer-shell-node.hpp +++ b/src/view/layer-shell/layer-shell-node.hpp @@ -29,8 +29,7 @@ class layer_shell_node_t : public wf::scene::translation_node_t, wf::region_t get_opaque_region() const override; protected: - wayfire_view view; + std::weak_ptr _view; std::unique_ptr kb_interaction; - wf::signal::connection_t on_view_destroy; }; } diff --git a/src/view/layer-shell/layer-shell.cpp b/src/view/layer-shell/layer-shell.cpp index 5ad51f3f6..ed8bb1ebc 100644 --- a/src/view/layer-shell/layer-shell.cpp +++ b/src/view/layer-shell/layer-shell.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "view/layer-shell/layer-shell-node.hpp" #include "wayfire/geometry.hpp" #include "wayfire/scene-operations.hpp" @@ -642,7 +643,7 @@ void wayfire_layer_shell_view::remove_anchored(bool reflow) */ class layer_shell_view_controller_t { - nonstd::observer_ptr view; + std::shared_ptr view; wf::wl_listener_wrapper on_destroy; public: @@ -650,16 +651,14 @@ class layer_shell_view_controller_t { on_destroy.set_callback([=] (auto) { delete this; }); on_destroy.connect(&lsurface->events.destroy); - - auto view = std::make_unique(lsurface); - this->view = {view}; - wf::get_core().add_view(std::move(view)); + view = wf::tracking_allocator_t::get() + .allocate(lsurface); + wf::view_interface_t::initialize_new(view.get()); } ~layer_shell_view_controller_t() { view->handle_destroy(); - view->unref(); } }; diff --git a/src/view/toplevel-node.cpp b/src/view/toplevel-node.cpp index 3a0cf4dd1..b14ef117b 100644 --- a/src/view/toplevel-node.cpp +++ b/src/view/toplevel-node.cpp @@ -6,14 +6,7 @@ wf::toplevel_view_node_t::toplevel_view_node_t(wayfire_toplevel_view view) : view_node_tag_t(view) { this->kb_interaction = std::make_unique(view); - on_view_destroy = [=] (view_destruct_signal *ev) - { - this->view = nullptr; - this->kb_interaction = std::make_unique(); - }; - - view->connect(&on_view_destroy); - this->view = view; + this->_view = view->weak_from_this(); } /** @@ -24,13 +17,13 @@ static constexpr double MIN_VISIBILITY_PC = 0.1; wf::keyboard_focus_node_t wf::toplevel_view_node_t::keyboard_refocus(wf::output_t *output) { + auto view = _view.lock(); if (!view) { return wf::keyboard_focus_node_t{}; } - if (!this->view->is_mapped() || !this->view->get_keyboard_focus_surface() || - this->view->minimized || !this->view->get_output()) + if (!view->is_mapped() || !view->get_keyboard_focus_surface() || view->minimized || !view->get_output()) { return wf::keyboard_focus_node_t{}; } @@ -78,9 +71,15 @@ wf::keyboard_interaction_t& wf::toplevel_view_node_t::keyboard_interaction() std::string wf::toplevel_view_node_t::stringify() const { - std::ostringstream out; - out << this->view; - return out.str() + " " + stringify_flags(); + if (auto view = _view.lock()) + { + std::ostringstream out; + out << view->self(); + return out.str() + " " + stringify_flags(); + } else + { + return "inert toplevel " + stringify_flags(); + } } class toplevel_view_render_instance_t : public wf::scene::translation_node_instance_t @@ -128,6 +127,7 @@ void wf::toplevel_view_node_t::gen_render_instances( std::optional wf::toplevel_view_node_t::to_texture() const { + auto view = _view.lock(); if (!view || !view->is_mapped() || (get_children().size() != 1)) { return {}; @@ -143,6 +143,7 @@ std::optional wf::toplevel_view_node_t::to_texture() const wf::region_t wf::toplevel_view_node_t::get_opaque_region() const { + auto view = _view.lock(); if (view && view->is_mapped() && view->get_wlr_surface()) { auto surf = view->get_wlr_surface(); diff --git a/src/view/toplevel-node.hpp b/src/view/toplevel-node.hpp index 38a224890..87aa9df45 100644 --- a/src/view/toplevel-node.hpp +++ b/src/view/toplevel-node.hpp @@ -30,8 +30,7 @@ class toplevel_view_node_t : public wf::scene::translation_node_t, wf::region_t get_opaque_region() const override; protected: - wayfire_toplevel_view view; + std::weak_ptr _view; std::unique_ptr kb_interaction; - wf::signal::connection_t on_view_destroy; }; } diff --git a/src/view/view-impl.hpp b/src/view/view-impl.hpp index 41dd72ed0..600794a3c 100644 --- a/src/view/view-impl.hpp +++ b/src/view/view-impl.hpp @@ -27,10 +27,6 @@ class view_interface_t::view_priv_impl { public: wlr_surface *wsurface = nullptr; - - /** Reference count to the view */ - int ref_cnt = 0; - size_t last_view_cnt = 0; bool keyboard_focus_enabled = true; diff --git a/src/view/view-keyboard-interaction.hpp b/src/view/view-keyboard-interaction.hpp index 4f688f9da..cf73a1fdf 100644 --- a/src/view/view-keyboard-interaction.hpp +++ b/src/view/view-keyboard-interaction.hpp @@ -13,29 +13,32 @@ */ class view_keyboard_interaction_t : public wf::keyboard_interaction_t { - wayfire_view view; + std::weak_ptr view; public: view_keyboard_interaction_t(wayfire_view _view) { - this->view = _view; + this->view = _view->weak_from_this(); } void handle_keyboard_enter(wf::seat_t *seat) override { - if (view->get_wlr_surface()) + if (auto ptr = view.lock()) { - auto pressed_keys = seat->get_pressed_keys(); + if (ptr->get_wlr_surface()) + { + auto pressed_keys = seat->get_pressed_keys(); - auto kbd = wlr_seat_get_keyboard(seat->seat); - wlr_seat_keyboard_notify_enter(seat->seat, view->get_wlr_surface(), - pressed_keys.data(), pressed_keys.size(), kbd ? &kbd->modifiers : NULL); + auto kbd = wlr_seat_get_keyboard(seat->seat); + wlr_seat_keyboard_notify_enter(seat->seat, ptr->get_wlr_surface(), + pressed_keys.data(), pressed_keys.size(), kbd ? &kbd->modifiers : NULL); + } } } void handle_keyboard_leave(wf::seat_t *seat) override { - if (view->get_wlr_surface()) + if (auto ptr = view.lock()) { wlr_seat_keyboard_notify_clear_focus(seat->seat); } diff --git a/src/view/view.cpp b/src/view/view.cpp index b6176942a..4c1cdde8d 100644 --- a/src/view/view.cpp +++ b/src/view/view.cpp @@ -126,7 +126,6 @@ void wf::view_interface_t::take_snapshot(wf::render_target_t& target) wf::view_interface_t::view_interface_t() { this->priv = std::make_unique(); - take_ref(); } void wf::view_interface_t::set_surface_root_node(scene::floating_inner_ptr surface_root_node) @@ -134,35 +133,19 @@ void wf::view_interface_t::set_surface_root_node(scene::floating_inner_ptr surfa this->priv->surface_root_node = surface_root_node; } -void wf::view_interface_t::take_ref() -{ - ++priv->ref_cnt; -} - -void wf::view_interface_t::unref() -{ - --priv->ref_cnt; - if (priv->ref_cnt <= 0) - { - destruct(); - } -} - class view_root_node_t : public wf::scene::floating_inner_node_t, public wf::view_node_tag_t { public: view_root_node_t(wf::view_interface_t *_view) : floating_inner_node_t(false), - view_node_tag_t(_view), view(_view) - { - view->connect(&on_destruct); - } + view_node_tag_t(_view), view(_view->weak_from_this()) + {} std::string stringify() const override { - if (view) + if (auto ptr = view.lock()) { std::ostringstream out; - out << this->view->self(); + out << ptr->self(); return "view-root-node of " + out.str() + " " + stringify_flags(); } else { @@ -171,11 +154,7 @@ class view_root_node_t : public wf::scene::floating_inner_node_t, public wf::vie } private: - wf::view_interface_t *view; - wf::signal::connection_t on_destruct = [=] (wf::view_destruct_signal *ev) - { - view = nullptr; - }; + std::weak_ptr view; }; void wf::view_interface_t::initialize() @@ -197,14 +176,9 @@ void wf::view_interface_t::deinitialize() this->_clear_data(); } -wf::view_interface_t::~view_interface_t() = default; - -void wf::view_interface_t::destruct() +wf::view_interface_t::~view_interface_t() { - view_destruct_signal ev; - ev.view = self(); - this->emit(&ev); - wf::get_core_impl().erase_view(self()); + wf::scene::remove_child(get_root_node()); } const wf::scene::floating_inner_ptr& wf::view_interface_t::get_root_node() const @@ -256,3 +230,14 @@ wlr_surface*wf::view_interface_t::get_wlr_surface() { return priv->wsurface; } + +void wf::view_interface_t::initialize_new(wayfire_view view) +{ + auto v = view->self(); /* non-owning copy */ + + v->initialize(); + if (!v->get_output()) + { + v->set_output(wf::get_core().get_active_output()); + } +} diff --git a/src/view/xdg-shell.cpp b/src/view/xdg-shell.cpp index bc5829ef6..125c02ed5 100644 --- a/src/view/xdg-shell.cpp +++ b/src/view/xdg-shell.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "xdg-shell/xdg-toplevel-view.hpp" #include "view-keyboard-interaction.hpp" @@ -315,7 +316,7 @@ wlr_surface*wayfire_xdg_popup::get_keyboard_focus_surface() */ class xdg_popup_controller_t { - nonstd::observer_ptr view; + std::shared_ptr view; wf::wl_listener_wrapper on_destroy; public: @@ -323,16 +324,13 @@ class xdg_popup_controller_t { on_destroy.set_callback([=] (auto) { delete this; }); on_destroy.connect(&popup->base->events.destroy); - - auto view = std::make_unique(popup); - this->view = {view}; - wf::get_core().add_view(std::move(view)); + view = wf::tracking_allocator_t::get() + .allocate(popup); + wf::view_interface_t::initialize_new(view.get()); } ~xdg_popup_controller_t() - { - view->unref(); - } + {} }; void create_xdg_popup(wlr_xdg_popup *popup) diff --git a/src/view/xdg-shell/xdg-toplevel-view.cpp b/src/view/xdg-shell/xdg-toplevel-view.cpp index 3471269c9..214ce119b 100644 --- a/src/view/xdg-shell/xdg-toplevel-view.cpp +++ b/src/view/xdg-shell/xdg-toplevel-view.cpp @@ -9,7 +9,9 @@ #include "../xdg-shell.hpp" #include "wayfire/debug.hpp" #include "wayfire/geometry.hpp" +#include "wayfire/nonstd/tracking-allocator.hpp" #include "wayfire/util.hpp" +#include "wayfire/view.hpp" #include #include #include @@ -464,7 +466,7 @@ void wf::init_xdg_decoration_handlers() */ class xdg_toplevel_controller_t { - nonstd::observer_ptr view; + std::shared_ptr view; wf::wl_listener_wrapper on_destroy; public: @@ -472,16 +474,13 @@ class xdg_toplevel_controller_t { on_destroy.set_callback([=] (auto) { delete this; }); on_destroy.connect(&toplevel->base->events.destroy); - - auto view = std::make_unique(toplevel); - this->view = {view}; - wf::get_core().add_view(std::move(view)); + view = wf::tracking_allocator_t::get() + .allocate(toplevel); + wf::view_interface_t::initialize_new(view.get()); } ~xdg_toplevel_controller_t() - { - view->unref(); - } + {} }; void wf::default_handle_new_xdg_toplevel(wlr_xdg_toplevel *toplevel) diff --git a/src/view/xwayland.cpp b/src/view/xwayland.cpp index 1bbfda81f..e992e3e45 100644 --- a/src/view/xwayland.cpp +++ b/src/view/xwayland.cpp @@ -4,6 +4,7 @@ #include "../core/core-impl.hpp" #include "../core/seat/cursor.hpp" #include +#include #include "wayfire/util.hpp" #include "xwayland/xwayland-helpers.hpp" @@ -26,7 +27,7 @@ namespace wf class xwayland_view_controller_t { nonstd::observer_ptr view_base; - nonstd::observer_ptr view_impl; + std::shared_ptr view_impl; wlr_xwayland_surface *xw; wf::wl_listener_wrapper on_destroy; @@ -62,9 +63,7 @@ class xwayland_view_controller_t } ~xwayland_view_controller_t() - { - view_impl->unref(); - } + {} bool is_dialog() { @@ -122,25 +121,29 @@ class xwayland_view_controller_t void create_view(wf::xw::view_type target_type) { - std::unique_ptr new_view; + std::shared_ptr new_view; switch (target_type) { case wf::xw::view_type::DND: - new_view = std::make_unique(xw); + new_view = wf::tracking_allocator_t::get() + .allocate(xw); break; case wf::xw::view_type::UNMANAGED: - new_view = std::make_unique(xw); + new_view = wf::tracking_allocator_t::get() + .allocate(xw); break; case wf::xw::view_type::NORMAL: - new_view = std::make_unique(xw); + new_view = wf::tracking_allocator_t::get() + .allocate(xw); break; } this->view_base = {dynamic_cast(new_view.get())}; this->view_impl = {new_view}; - wf::get_core().add_view(std::move(new_view)); + wf::view_interface_t::initialize_new(view_impl.get()); + if (xw->mapped) { view_base->map(xw->surface); @@ -170,7 +173,6 @@ class xwayland_view_controller_t } view_base->destroy(); - view_impl->unref(); view_base = nullptr; view_impl = nullptr; diff --git a/src/view/xwayland/xwayland-unmanaged-view.hpp b/src/view/xwayland/xwayland-unmanaged-view.hpp index 15665c9c5..f6e98cae0 100644 --- a/src/view/xwayland/xwayland-unmanaged-view.hpp +++ b/src/view/xwayland/xwayland-unmanaged-view.hpp @@ -1,6 +1,7 @@ #pragma once #include "config.h" +#include "wayfire/core.hpp" #include "wayfire/output.hpp" #include "wayfire/unstable/translation-node.hpp" #include "wayfire/util.hpp" @@ -21,18 +22,13 @@ class xwayland_unmanaged_view_node_t : public wf::scene::translation_node_t, pub public: xwayland_unmanaged_view_node_t(wayfire_view view) : view_node_tag_t(view) { + _view = view->weak_from_this(); this->kb_interaction = std::make_unique(view); - on_view_destroy = [=] (view_destruct_signal *ev) - { - this->view = nullptr; - this->kb_interaction = std::make_unique(); - }; - - view->connect(&on_view_destroy); } wf::keyboard_focus_node_t keyboard_refocus(wf::output_t *output) override { + auto view = _view.lock(); if (!view || !view->get_keyboard_focus_surface()) { return wf::keyboard_focus_node_t{}; @@ -62,15 +58,20 @@ class xwayland_unmanaged_view_node_t : public wf::scene::translation_node_t, pub std::string stringify() const override { - std::ostringstream out; - out << this->view; - return "unmanaged " + out.str() + " " + stringify_flags(); + if (auto view = _view.lock()) + { + std::ostringstream out; + out << view->self(); + return "unmanaged " + out.str() + " " + stringify_flags(); + } else + { + return "inert unmanaged " + stringify_flags(); + } } protected: - wayfire_toplevel_view view; + std::weak_ptr _view; std::unique_ptr kb_interaction; - wf::signal::connection_t on_view_destroy; }; } @@ -258,10 +259,9 @@ class wayfire_dnd_xwayland_view : public wayfire_unmanaged_xwayland_view return wf::xw::view_type::DND; } - void destruct() override + ~wayfire_dnd_xwayland_view() { LOGD("Destroying a Xwayland drag icon"); - wayfire_unmanaged_xwayland_view::destruct(); } void deinitialize() override