diff --git a/src/compositor_state.h b/src/compositor_state.h
index 0ec20bf..25d7c83 100644
--- a/src/compositor_state.h
+++ b/src/compositor_state.h
@@ -19,10 +19,12 @@ along with this program. If not, see .
#define MIRACLE_WM_COMPOSITOR_STATE_H
#include
-#include
+#include
namespace miracle
{
+class Container;
+
enum class WindowManagerMode
{
normal = 0,
@@ -37,7 +39,7 @@ struct CompositorState
{
mir::geometry::Point cursor_position;
WindowManagerMode mode = WindowManagerMode::normal;
- miral::Window active_window;
+ std::shared_ptr active;
};
}
diff --git a/src/container.cpp b/src/container.cpp
index 14ea7fc..d4140d4 100644
--- a/src/container.cpp
+++ b/src/container.cpp
@@ -31,7 +31,7 @@ using namespace miracle;
ContainerType miracle::container_type_from_string(std::string const& str)
{
if (str == "tiled")
- return ContainerType::tiled;
+ return ContainerType::leaf;
else if (str == "floating")
return ContainerType::floating;
else if (str == "shell")
diff --git a/src/container.h b/src/container.h
index 140a1bc..828aef4 100644
--- a/src/container.h
+++ b/src/container.h
@@ -43,7 +43,7 @@ class Output;
enum class ContainerType
{
none,
- tiled,
+ leaf,
floating,
shell,
parent
@@ -104,6 +104,7 @@ public:
virtual uint32_t animation_handle() const = 0;
virtual void animation_handle(uint32_t) = 0;
virtual bool is_focused() const = 0;
+ virtual bool is_fullscreen() const = 0;
virtual std::optional window() const = 0;
virtual bool select_next(Direction) = 0;
virtual bool pinned() const = 0;
diff --git a/src/floating_container.cpp b/src/floating_container.cpp
index 0b04bc8..4f9faab 100644
--- a/src/floating_container.cpp
+++ b/src/floating_container.cpp
@@ -30,7 +30,7 @@ using namespace miracle;
FloatingContainer::FloatingContainer(
miral::Window const& window,
- miral::MinimalWindowManager& wm,
+ std::shared_ptr const& wm,
WindowController& window_controller,
Workspace* workspace,
CompositorState const& state) :
@@ -84,31 +84,31 @@ size_t FloatingContainer::get_min_width() const
void FloatingContainer::handle_ready()
{
auto& info = window_controller.info_for(window_);
- wm.handle_window_ready(info);
+ wm->handle_window_ready(info);
}
void FloatingContainer::handle_modify(miral::WindowSpecification const& modifications)
{
auto& info = window_controller.info_for(window_);
- wm.handle_modify_window(info, modifications);
+ wm->handle_modify_window(info, modifications);
}
void FloatingContainer::handle_request_move(MirInputEvent const* input_event)
{
- wm.handle_request_move(
+ wm->handle_request_move(
window_controller.info_for(window_), input_event);
}
void FloatingContainer::handle_request_resize(
MirInputEvent const* input_event, MirResizeEdge edge)
{
- wm.handle_request_resize(
+ wm->handle_request_resize(
window_controller.info_for(window_), input_event, edge);
}
void FloatingContainer::handle_raise()
{
- wm.handle_raise_window(window_controller.info_for(window_));
+ wm->handle_raise_window(window_controller.info_for(window_));
}
void FloatingContainer::on_open()
@@ -118,23 +118,26 @@ void FloatingContainer::on_open()
void FloatingContainer::on_focus_gained()
{
- wm.advise_focus_gained(window_controller.info_for(window_));
+ if (get_output()->get_active_workspace()->get_workspace() != workspace_->get_workspace())
+ return;
+
+ wm->advise_focus_gained(window_controller.info_for(window_));
}
void FloatingContainer::on_focus_lost()
{
- wm.advise_focus_lost(window_controller.info_for(window_));
+ wm->advise_focus_lost(window_controller.info_for(window_));
}
void FloatingContainer::on_move_to(geom::Point const& top_left)
{
- wm.advise_move_to(window_controller.info_for(window_), top_left);
+ wm->advise_move_to(window_controller.info_for(window_), top_left);
}
mir::geometry::Rectangle FloatingContainer::confirm_placement(
MirWindowState state, mir::geometry::Rectangle const& placement)
{
- return wm.confirm_placement_on_display(
+ return wm->confirm_placement_on_display(
window_controller.info_for(window_),
state,
placement);
@@ -195,6 +198,11 @@ Workspace* FloatingContainer::get_workspace() const
return workspace_;
}
+void FloatingContainer::set_workspace(Workspace* workspace)
+{
+ workspace_ = workspace;
+}
+
Output* FloatingContainer::get_output() const
{
return workspace_->get_output();
@@ -222,7 +230,12 @@ void FloatingContainer::animation_handle(uint32_t handle)
bool FloatingContainer::is_focused() const
{
- return state.active_window == window_;
+ return state.active.get() == this;
+}
+
+bool FloatingContainer::is_fullscreen() const
+{
+ return window_controller.is_fullscreen(window_);
}
ContainerType FloatingContainer::get_type() const
diff --git a/src/floating_container.h b/src/floating_container.h
index fce1374..dad06df 100644
--- a/src/floating_container.h
+++ b/src/floating_container.h
@@ -33,7 +33,7 @@ class FloatingContainer : public Container
public:
FloatingContainer(
miral::Window const&,
- miral::MinimalWindowManager& wm,
+ std::shared_ptr const& wm,
WindowController& window_controller,
Workspace* workspace,
CompositorState const& state);
@@ -67,12 +67,14 @@ public:
void restore_state(MirWindowState state) override;
std::optional restore_state() override;
Workspace* get_workspace() const override;
+ void set_workspace(Workspace*);
Output* get_output() const override;
glm::mat4 get_transform() const override;
void set_transform(glm::mat4 transform) override;
uint32_t animation_handle() const override;
void animation_handle(uint32_t uint_32) override;
bool is_focused() const override;
+ bool is_fullscreen() const override;
ContainerType get_type() const override;
glm::mat4 get_workspace_transform() const override;
glm::mat4 get_output_transform() const override;
@@ -85,7 +87,7 @@ public:
private:
miral::Window window_;
- miral::MinimalWindowManager& wm;
+ std::shared_ptr wm;
WindowController& window_controller;
CompositorState const& state;
diff --git a/src/i3_command_executor.cpp b/src/i3_command_executor.cpp
index 54e77fe..9fff9c4 100644
--- a/src/i3_command_executor.cpp
+++ b/src/i3_command_executor.cpp
@@ -198,7 +198,7 @@ void I3CommandExecutor::process_focus(I3Command const& command, I3ScopedCommandL
if (!container)
return;
- if (container->get_type() != ContainerType::tiled)
+ if (container->get_type() != ContainerType::leaf)
{
mir::log_warning("Cannot focus prev when a tiling window is not selected");
return;
@@ -224,7 +224,7 @@ void I3CommandExecutor::process_focus(I3Command const& command, I3ScopedCommandL
if (!container)
return;
- if (container->get_type() != ContainerType::tiled)
+ if (container->get_type() != ContainerType::leaf)
{
mir::log_warning("Cannot focus prev when a tiling window is not selected");
return;
@@ -332,10 +332,10 @@ void I3CommandExecutor::process_move(I3Command const& command, I3ScopedCommandLi
auto const& arg1 = command.arguments[index++];
if (arg1 == "center")
{
- auto active_window = policy.get_state().active_window;
+ auto active = policy.get_state().active;
auto area = active_output->get_area();
- float x = (float)area.size.width.as_int() / 2.f - (float)active_window.size().width.as_int() / 2.f;
- float y = (float)area.size.height.as_int() / 2.f - (float)active_window.size().height.as_int() / 2.f;
+ float x = (float)area.size.width.as_int() / 2.f - (float)active->get_visible_area().size.width.as_int() / 2.f;
+ float y = (float)area.size.height.as_int() / 2.f - (float)active->get_visible_area().size.height.as_int() / 2.f;
policy.try_move_to((int)x, (int)y);
}
else if (arg1 == "mouse")
@@ -392,9 +392,9 @@ void I3CommandExecutor::process_move(I3Command const& command, I3ScopedCommandLi
y = end_y;
}
- auto active_window = policy.get_state().active_window;
- float x_pos = x / 2.f - (float)active_window.size().width.as_int() / 2.f;
- float y_pos = y / 2.f - (float)active_window.size().height.as_int() / 2.f;
+ auto active = policy.get_state().active;
+ float x_pos = x / 2.f - (float)active->get_visible_area().size.width.as_int() / 2.f;
+ float y_pos = y / 2.f - (float)active->get_visible_area().size.height.as_int() / 2.f;
policy.try_move_to((int)x_pos, (int)y_pos);
return;
}
diff --git a/src/leaf_container.cpp b/src/leaf_container.cpp
index 9a5ce03..b17aba5 100644
--- a/src/leaf_container.cpp
+++ b/src/leaf_container.cpp
@@ -35,7 +35,7 @@ LeafContainer::LeafContainer(
TilingWindowTree* tree,
std::shared_ptr const& parent,
CompositorState const& state) :
- node_interface { node_interface },
+ window_controller {node_interface },
logical_area { std::move(area) },
config { config },
tree { tree },
@@ -111,10 +111,10 @@ geom::Rectangle LeafContainer::get_visible_area() const
void LeafContainer::constrain()
{
- if (node_interface.is_fullscreen(window_))
- node_interface.noclip(window_);
+ if (window_controller.is_fullscreen(window_))
+ window_controller.noclip(window_);
else
- node_interface.clip(window_, get_visible_area());
+ window_controller.clip(window_, get_visible_area());
}
size_t LeafContainer::get_min_width() const
@@ -135,7 +135,7 @@ void LeafContainer::handle_ready()
void LeafContainer::handle_modify(miral::WindowSpecification const& modifications)
{
- auto const& info = node_interface.info_for(window_);
+ auto const& info = window_controller.info_for(window_);
// TODO: Check if the current workspace is active. If not, return early.
@@ -160,12 +160,12 @@ void LeafContainer::handle_modify(miral::WindowSpecification const& modification
mods.size().consume();
}
- node_interface.modify(window_, mods);
+ window_controller.modify(window_, mods);
}
void LeafContainer::handle_raise()
{
- node_interface.select_active_window(window_);
+ window_controller.select_active_window(window_);
}
bool LeafContainer::resize(miracle::Direction direction)
@@ -181,13 +181,13 @@ void LeafContainer::show()
void LeafContainer::hide()
{
- before_shown_state = node_interface.get_state(window_);
+ before_shown_state = window_controller.get_state(window_);
next_state = mir_window_state_hidden;
}
bool LeafContainer::toggle_fullscreen()
{
- if (node_interface.is_fullscreen(window_))
+ if (window_controller.is_fullscreen(window_))
next_state = mir_window_state_restored;
else
next_state = mir_window_state_fullscreen;
@@ -206,7 +206,7 @@ mir::geometry::Rectangle LeafContainer::confirm_placement(
void LeafContainer::on_open()
{
- node_interface.open(window_);
+ window_controller.open(window_);
}
void LeafContainer::on_focus_gained()
@@ -224,14 +224,14 @@ void LeafContainer::on_move_to(geom::Point const&)
bool LeafContainer::is_fullscreen() const
{
- return node_interface.is_fullscreen(window_);
+ return window_controller.is_fullscreen(window_);
}
void LeafContainer::commit_changes()
{
if (next_state)
{
- node_interface.change_state(window_, next_state.value());
+ window_controller.change_state(window_, next_state.value());
constrain();
next_state.reset();
}
@@ -241,9 +241,9 @@ void LeafContainer::commit_changes()
auto previous = get_visible_area();
logical_area = next_logical_area.value();
next_logical_area.reset();
- if (!node_interface.is_fullscreen(window_))
+ if (!window_controller.is_fullscreen(window_))
{
- node_interface.set_rectangle(window_, previous, get_visible_area());
+ window_controller.set_rectangle(window_, previous, get_visible_area());
constrain();
}
}
@@ -272,6 +272,11 @@ void LeafContainer::toggle_layout()
tree->toggle_layout(*this);
}
+void LeafContainer::set_tree(TilingWindowTree* tree_)
+{
+ tree = tree_;
+}
+
void LeafContainer::restore_state(MirWindowState state)
{
restore_state_ = state;
@@ -316,12 +321,12 @@ void LeafContainer::animation_handle(uint32_t handle)
bool LeafContainer::is_focused() const
{
- return state.active_window == window_;
+ return state.active.get() == this;
}
ContainerType LeafContainer::get_type() const
{
- return ContainerType::tiled;
+ return ContainerType::leaf;
}
bool LeafContainer::select_next(miracle::Direction direction)
diff --git a/src/leaf_container.h b/src/leaf_container.h
index b4555d0..f204e06 100644
--- a/src/leaf_container.h
+++ b/src/leaf_container.h
@@ -55,7 +55,7 @@ public:
void set_state(MirWindowState state);
void show();
void hide();
- bool is_fullscreen() const;
+ bool is_fullscreen() const override;
void constrain() override;
size_t get_min_width() const override;
size_t get_min_height() const override;
@@ -75,6 +75,7 @@ public:
void request_horizontal_layout() override;
void request_vertical_layout() override;
void toggle_layout() override;
+ void set_tree(TilingWindowTree* tree);
[[nodiscard]] TilingWindowTree* get_tree() const { return tree; }
[[nodiscard]] std::optional window() const override { return window_; }
@@ -97,7 +98,7 @@ public:
bool move_to(int, int) override;
private:
- WindowController& node_interface;
+ WindowController& window_controller;
geom::Rectangle logical_area;
std::optional next_logical_area;
std::shared_ptr config;
diff --git a/src/miracle_config.cpp b/src/miracle_config.cpp
index b5cc7ef..0f12929 100644
--- a/src/miracle_config.cpp
+++ b/src/miracle_config.cpp
@@ -811,7 +811,7 @@ void FilesystemConfiguration::_load()
{
auto num = workspace["number"].as();
auto type = container_type_from_string(workspace["layout"].as());
- if (type != ContainerType::tiled && type != ContainerType::floating)
+ if (type != ContainerType::leaf && type != ContainerType::floating)
{
mir::log_error("layout should be 'tiled' or 'floating': L%d:%d", workspace["layout"].Mark().line, workspace["layout"].Mark().column);
continue;
@@ -1155,5 +1155,5 @@ WorkspaceConfig FilesystemConfiguration::get_workspace_config(int key) const
return config;
}
- return { key, ContainerType::tiled };
+ return { key, ContainerType::leaf };
}
\ No newline at end of file
diff --git a/src/miracle_config.h b/src/miracle_config.h
index 27edfc8..258b416 100644
--- a/src/miracle_config.h
+++ b/src/miracle_config.h
@@ -129,7 +129,7 @@ struct BorderConfig
struct WorkspaceConfig
{
int num = -1;
- ContainerType layout = ContainerType::tiled;
+ ContainerType layout = ContainerType::leaf;
};
class MiracleConfig
diff --git a/src/output.cpp b/src/output.cpp
index fdc3c3c..a5b8602 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -42,7 +42,7 @@ Output::Output(
WorkspaceManager& workspace_manager,
geom::Rectangle const& area,
miral::WindowManagerTools const& tools,
- miral::MinimalWindowManager& floating_window_manager,
+ std::shared_ptr const& floating_window_manager,
CompositorState& state,
std::shared_ptr const& config,
WindowController& node_interface,
@@ -82,13 +82,13 @@ bool Output::handle_pointer_event(const MirPointerEvent* event)
return true;
auto const action = mir_pointer_event_action(event);
- if (has_clicked_floating_window || get_active_workspace()->has_floating_window(state.active_window))
+ if (has_clicked_floating_window || get_active_workspace()->has_floating_window(state.active))
{
if (action == mir_pointer_action_button_down)
has_clicked_floating_window = true;
else if (action == mir_pointer_action_button_up)
has_clicked_floating_window = false;
- return floating_window_manager.handle_pointer_event(event);
+ return floating_window_manager->handle_pointer_event(event);
}
return false;
@@ -106,16 +106,16 @@ ContainerType Output::allocate_position(
return get_active_workspace()->allocate_position(app_info, requested_specification, ideal_type);
}
-std::shared_ptr Output::advise_new_window(
+std::shared_ptr Output::create_container(
miral::WindowInfo const& window_info, ContainerType type) const
{
- return get_active_workspace()->advise_new_window(window_info, type);
+ return get_active_workspace()->create_container(window_info, type);
}
-void Output::advise_delete_window(const std::shared_ptr& container)
+void Output::delete_container(std::shared_ptr const &container)
{
auto workspace = container->get_workspace();
- workspace->advise_delete_window(container);
+ workspace->delete_container(container);
}
bool Output::select_window_from_point(int x, int y) const
@@ -309,20 +309,13 @@ std::vector Output::collect_all_windows() const
void Output::request_toggle_active_float()
{
- if (tools.active_window() == Window())
+ if (!state.active)
{
- mir::log_warning("request_toggle_active_float: active window unset");
+ mir::log_warning("request_toggle_active_float: active unset");
return;
}
- auto container = window_controller.get_container(state.active_window);
- if (!container)
- {
- mir::log_error("request_toggle_active_float: container not found");
- return;
- }
-
- container->get_workspace()->toggle_floating(container);
+ state.active->get_workspace()->toggle_floating(state.active);
}
void Output::add_immediately(miral::Window& window, ContainerType hint)
@@ -336,10 +329,15 @@ void Output::add_immediately(miral::Window& window, ContainerType hint)
ContainerType type = allocate_position(tools.info_for(window.application()), spec, hint);
tools.modify_window(window, spec);
- auto container = advise_new_window(window_controller.info_for(window), type);
+ auto container = create_container(window_controller.info_for(window), type);
container->handle_ready();
}
+void Output::graft(std::shared_ptr const& container)
+{
+ get_active_workspace()->graft(container);
+}
+
geom::Rectangle Output::get_workspace_rectangle(int workspace) const
{
// TODO: Support vertical workspaces one day in the future
diff --git a/src/output.h b/src/output.h
index 13ed2b9..b89c68d 100644
--- a/src/output.h
+++ b/src/output.h
@@ -44,7 +44,7 @@ public:
WorkspaceManager& workspace_manager,
geom::Rectangle const& area,
miral::WindowManagerTools const& tools,
- miral::MinimalWindowManager& floating_window_manager,
+ std::shared_ptr const& floating_window_manager,
CompositorState& state,
std::shared_ptr const& options,
WindowController&,
@@ -53,8 +53,8 @@ public:
bool handle_pointer_event(MirPointerEvent const* event);
ContainerType allocate_position(miral::ApplicationInfo const& app_info, miral::WindowSpecification& requested_specification, ContainerType hint = ContainerType::none);
- [[nodiscard]] std::shared_ptr advise_new_window(miral::WindowInfo const& window_info, ContainerType type) const;
- void advise_delete_window(std::shared_ptr const& container);
+ [[nodiscard]] std::shared_ptr create_container(miral::WindowInfo const& window_info, ContainerType type) const;
+ void delete_container(std::shared_ptr const &container);
[[nodiscard]] bool select_window_from_point(int x, int y) const;
void advise_new_workspace(int workspace);
void advise_workspace_deleted(int workspace);
@@ -70,8 +70,12 @@ public:
/// Immediately requests that the provided window be added to the output
/// with the provided type. This is a deviation away from the typical
/// window-adding flow where you first call 'place_new_window' followed
- /// by 'advise_new_window'.
+ /// by 'create_container'.
void add_immediately(miral::Window& window, ContainerType hint = ContainerType::none);
+
+ /// Takes an existing [Container] object and places it in an appropriate position
+ /// on the active [Workspace].
+ void graft(std::shared_ptr const& container);
void set_is_active(bool new_is_active) { is_active_ = new_is_active; }
void set_transform(glm::mat4 const& in);
void set_position(glm::vec2 const&);
@@ -95,7 +99,7 @@ private:
miral::Output output;
WorkspaceManager& workspace_manager;
miral::WindowManagerTools tools;
- miral::MinimalWindowManager& floating_window_manager;
+ std::shared_ptr floating_window_manager;
CompositorState& state;
geom::Rectangle area;
std::shared_ptr config;
diff --git a/src/parent_container.cpp b/src/parent_container.cpp
index f6d3ffb..773580a 100644
--- a/src/parent_container.cpp
+++ b/src/parent_container.cpp
@@ -584,6 +584,11 @@ void ParentContainer::toggle_layout()
{
}
+void ParentContainer::set_tree(TilingWindowTree* tree_)
+{
+ tree = tree_;
+}
+
void ParentContainer::on_focus_gained()
{
}
@@ -599,7 +604,7 @@ void ParentContainer::on_move_to(mir::geometry::Point const& top_left)
mir::geometry::Rectangle
ParentContainer::confirm_placement(MirWindowState state, mir::geometry::Rectangle const& rectangle)
{
- return mir::geometry::Rectangle();
+ return rectangle;
}
ContainerType ParentContainer::get_type() const
@@ -697,3 +702,8 @@ bool ParentContainer::move_to(int x, int y)
{
return false;
}
+
+bool ParentContainer::is_fullscreen() const
+{
+ return false;
+}
diff --git a/src/parent_container.h b/src/parent_container.h
index baba736..318b23d 100644
--- a/src/parent_container.h
+++ b/src/parent_container.h
@@ -78,6 +78,7 @@ public:
void request_horizontal_layout() override;
void request_vertical_layout() override;
void toggle_layout() override;
+ void set_tree(TilingWindowTree*);
void on_focus_gained() override;
void on_focus_lost() override;
void on_move_to(mir::geometry::Point const& top_left) override;
@@ -104,6 +105,8 @@ public:
bool move_by(Direction direction, int pixels) override;
bool move_to(int x, int y) override;
+ bool is_fullscreen() const override;
+
private:
WindowController& node_interface;
geom::Rectangle logical_area;
diff --git a/src/policy.cpp b/src/policy.cpp
index c2e6256..8419ef6 100644
--- a/src/policy.cpp
+++ b/src/policy.cpp
@@ -50,7 +50,7 @@ Policy::Policy(
SurfaceTracker& surface_tracker,
mir::Server const& server) :
window_manager_tools { tools },
- floating_window_manager(tools, config->get_input_event_modifier()),
+ floating_window_manager(std::make_shared(tools, config->get_input_event_modifier())),
external_client_launcher { external_client_launcher },
runner { runner },
config { config },
@@ -243,7 +243,7 @@ void Policy::advise_new_window(miral::WindowInfo const& window_info)
auto shared_output = pending_output.lock();
if (!shared_output)
{
- mir::log_warning("advise_new_window: output unavailable");
+ mir::log_warning("create_container: output unavailable");
auto window = window_info.window();
if (!output_list.empty())
{
@@ -262,7 +262,7 @@ void Policy::advise_new_window(miral::WindowInfo const& window_info)
return;
}
- auto container = shared_output->advise_new_window(window_info, pending_type);
+ auto container = shared_output->create_container(window_info, pending_type);
container->animation_handle(animator.register_animateable());
container->on_open();
@@ -287,7 +287,6 @@ void Policy::handle_window_ready(miral::WindowInfo& window_info)
void Policy::advise_focus_gained(const miral::WindowInfo& window_info)
{
- state.active_window = window_info.window();
auto container = window_controller.get_container(window_info.window());
if (!container)
{
@@ -295,12 +294,12 @@ void Policy::advise_focus_gained(const miral::WindowInfo& window_info)
return;
}
+ state.active = container;
container->on_focus_gained();
}
void Policy::advise_focus_lost(const miral::WindowInfo& window_info)
{
- state.active_window = Window();
auto container = window_controller.get_container(window_info.window());
if (!container)
{
@@ -308,6 +307,8 @@ void Policy::advise_focus_lost(const miral::WindowInfo& window_info)
return;
}
+ if (container == state.active)
+ state.active = nullptr;
container->on_focus_lost();
}
@@ -326,17 +327,17 @@ void Policy::advise_delete_window(const miral::WindowInfo& window_info)
auto container = window_controller.get_container(window_info.window());
if (!container)
{
- mir::log_error("advise_delete_window: container is not provided");
+ mir::log_error("delete_container: container is not provided");
return;
}
if (container->get_output())
- container->get_output()->advise_delete_window(container);
+ container->get_output()->delete_container(container);
surface_tracker.remove(window_info.window());
- if (state.active_window == window_info.window())
- state.active_window = Window();
+ if (state.active == container)
+ state.active = nullptr;
}
void Policy::advise_move_to(miral::WindowInfo const& window_info, geom::Point top_left)
@@ -547,21 +548,14 @@ void Policy::try_toggle_resize_mode()
return;
}
- auto const& window = state.active_window;
- if (!window)
- {
- state.mode = WindowManagerMode::normal;
- return;
- }
-
- auto container = window_controller.get_container(window);
+ auto container = state.active;
if (!container)
{
state.mode = WindowManagerMode::normal;
return;
}
- if (container->get_type() != ContainerType::tiled)
+ if (container->get_type() != ContainerType::leaf)
{
state.mode = WindowManagerMode::normal;
return;
@@ -580,11 +574,10 @@ bool Policy::try_request_vertical()
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- container->request_vertical_layout();
+ state.active->request_vertical_layout();
return true;
}
@@ -593,11 +586,10 @@ bool Policy::try_toggle_layout()
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- container->toggle_layout();
+ state.active->toggle_layout();
return true;
}
@@ -606,11 +598,10 @@ bool Policy::try_request_horizontal()
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- container->request_horizontal_layout();
+ state.active->request_horizontal_layout();
return true;
}
@@ -619,11 +610,10 @@ bool Policy::try_resize(miracle::Direction direction)
if (state.mode != WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->resize(direction);
+ return state.active->resize(direction);
}
bool Policy::try_move(miracle::Direction direction)
@@ -631,11 +621,10 @@ bool Policy::try_move(miracle::Direction direction)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->move(direction);
+ return state.active->move(direction);
}
bool Policy::try_move_by(miracle::Direction direction, int pixels)
@@ -643,11 +632,10 @@ bool Policy::try_move_by(miracle::Direction direction, int pixels)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->move_by(direction, pixels);
+ return state.active->move_by(direction, pixels);
}
bool Policy::try_move_to(int x, int y)
@@ -655,11 +643,10 @@ bool Policy::try_move_to(int x, int y)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->move_to(x, y);
+ return state.active->move_to(x, y);
}
bool Policy::try_select(miracle::Direction direction)
@@ -667,11 +654,10 @@ bool Policy::try_select(miracle::Direction direction)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->select_next(direction);
+ return state.active->select_next(direction);
}
bool Policy::try_close_window()
@@ -679,7 +665,14 @@ bool Policy::try_close_window()
if (!active_output)
return false;
- window_controller.close(state.active_window);
+ if (!state.active)
+ return false;
+
+ auto window = state.active->window();
+ if (!window)
+ return false;
+
+ window_controller.close(window.value());
return true;
}
@@ -694,11 +687,10 @@ bool Policy::try_toggle_fullscreen()
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->toggle_fullscreen();
+ return state.active->toggle_fullscreen();
}
bool Policy::select_workspace(int number)
@@ -718,21 +710,18 @@ bool Policy::move_active_to_workspace(int number)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!active_output || !state.active_window)
+ if (!active_output || !state.active)
return false;
- auto& info = window_controller.info_for(state.active_window);
- if (window_helpers::is_window_fullscreen(info.state()))
+ if (state.active->is_fullscreen())
return false;
- auto container = window_controller.get_container(state.active_window);
- auto window_to_move = state.active_window;
- active_output->advise_delete_window(container);
- state.active_window = Window();
+ auto to_move = state.active;
+ active_output->delete_container(state.active);
+ state.active = nullptr;
auto screen_to_move_to = workspace_manager.request_workspace(active_output, number);
- screen_to_move_to->add_immediately(window_to_move, ContainerType::tiled);
-
+ screen_to_move_to->graft(to_move);
return true;
}
@@ -753,11 +742,10 @@ bool Policy::toggle_pinned_to_workspace()
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->pinned(!container->pinned());
+ return state.active->pinned(!state.active->pinned());
}
bool Policy::set_is_pinned(bool pinned)
@@ -765,9 +753,8 @@ bool Policy::set_is_pinned(bool pinned)
if (state.mode == WindowManagerMode::resizing)
return false;
- if (!state.active_window)
+ if (!state.active)
return false;
- auto container = window_controller.get_container(state.active_window);
- return container->pinned(pinned);
+ return state.active->pinned(pinned);
}
\ No newline at end of file
diff --git a/src/policy.h b/src/policy.h
index 3622e53..6b2c7f9 100644
--- a/src/policy.h
+++ b/src/policy.h
@@ -130,7 +130,7 @@ private:
ContainerType pending_type;
std::vector orphaned_window_list;
miral::WindowManagerTools window_manager_tools;
- miral::MinimalWindowManager floating_window_manager;
+ std::shared_ptr floating_window_manager;
AutoRestartingLauncher& external_client_launcher;
miral::MirRunner& runner;
std::shared_ptr config;
diff --git a/src/renderer.cpp b/src/renderer.cpp
index e1688fe..66f1738 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -225,7 +225,7 @@ Renderer::DrawData Renderer::get_draw_data(mir::graphics::Renderable const& rend
auto tools = WindowToolsAccessor::get_instance().get_tools();
auto& info = tools.info_for(window);
auto userdata = static_pointer_cast(info.userdata());
- data.needs_outline = (userdata->get_type() == ContainerType::tiled || userdata->get_type() == ContainerType::floating)
+ data.needs_outline = (userdata->get_type() == ContainerType::leaf || userdata->get_type() == ContainerType::floating)
&& !info.parent();
data.workspace_transform = userdata->get_output_transform() * userdata->get_workspace_transform();
data.is_focused = userdata->is_focused();
diff --git a/src/shell_component_container.cpp b/src/shell_component_container.cpp
index 62544b9..be33d0c 100644
--- a/src/shell_component_container.cpp
+++ b/src/shell_component_container.cpp
@@ -230,4 +230,9 @@ bool ShellComponentContainer::move_to(int x, int y)
return false;
}
+bool ShellComponentContainer::is_fullscreen() const
+{
+ return false;
+}
+
} // miracle
\ No newline at end of file
diff --git a/src/shell_component_container.h b/src/shell_component_container.h
index 4ac1931..fd66ddc 100644
--- a/src/shell_component_container.h
+++ b/src/shell_component_container.h
@@ -77,6 +77,8 @@ public:
bool move_by(Direction direction, int pixels) override;
bool move_to(int x, int y) override;
+ bool is_fullscreen() const override;
+
private:
miral::Window window_;
WindowController& window_controller;
diff --git a/src/tiling_window_tree.cpp b/src/tiling_window_tree.cpp
index e84e804..6108dfa 100644
--- a/src/tiling_window_tree.cpp
+++ b/src/tiling_window_tree.cpp
@@ -93,6 +93,20 @@ std::shared_ptr TilingWindowTree::confirm_window(
return parent->confirm_window(window_info.window());
}
+void TilingWindowTree::graft(std::shared_ptr const& parent)
+{
+ parent->set_tree(this);
+ root_lane->graft_existing(parent, root_lane->num_nodes());
+ root_lane->commit_changes();
+}
+
+void TilingWindowTree::graft(std::shared_ptr const& leaf)
+{
+ leaf->set_tree(this);
+ root_lane->graft_existing(leaf, root_lane->num_nodes());
+ root_lane->commit_changes();
+}
+
bool TilingWindowTree::resize_container(miracle::Direction direction, Container& container)
{
if (is_active_window_fullscreen)
@@ -363,8 +377,8 @@ std::shared_ptr TilingWindowTree::handle_select(
// 4. If none match, we return nullptr
bool is_vertical = is_vertical_direction(direction);
bool is_negative = is_negative_direction(direction);
- auto& current_node = from;
- auto parent = Container::as_parent(current_node.get_parent().lock());
+ auto current_node = from.shared_from_this();
+ auto parent = Container::as_parent(current_node->get_parent().lock());
if (!parent)
{
mir::log_warning("Cannot handle_select the root node");
@@ -390,7 +404,7 @@ std::shared_ptr TilingWindowTree::handle_select(
}
}
- current_node = *parent;
+ current_node = parent;
parent = Container::as_parent(parent->get_parent().lock());
} while (parent != nullptr);
@@ -609,7 +623,7 @@ bool TilingWindowTree::advise_fullscreen_container(LeafContainer& container)
bool TilingWindowTree::advise_restored_container(LeafContainer& container)
{
auto active = active_container();
- if (active->window() == container.window().value() && is_active_window_fullscreen)
+ if (active && active->window() == container.window().value() && is_active_window_fullscreen)
{
is_active_window_fullscreen = false;
container.set_logical_area(container.get_logical_area());
@@ -756,12 +770,5 @@ Workspace* TilingWindowTree::get_workspace() const
std::shared_ptr TilingWindowTree::active_container() const
{
- if (!state.active_window)
- return nullptr;
-
- auto container = window_controller.get_container(state.active_window);
- if (!container)
- return nullptr;
-
- return Container::as_leaf(container);
+ return Container::as_leaf(state.active);
}
\ No newline at end of file
diff --git a/src/tiling_window_tree.h b/src/tiling_window_tree.h
index c76a037..70a8906 100644
--- a/src/tiling_window_tree.h
+++ b/src/tiling_window_tree.h
@@ -68,6 +68,9 @@ public:
miral::WindowInfo const&,
std::shared_ptr const& container);
+ void graft(std::shared_ptr const&);
+ void graft(std::shared_ptr const&);
+
/// Try to resize the current active window in the provided direction
bool resize_container(Direction direction, Container&);
diff --git a/src/window_manager_tools_window_controller.cpp b/src/window_manager_tools_window_controller.cpp
index 565e0f3..ee9ddac 100644
--- a/src/window_manager_tools_window_controller.cpp
+++ b/src/window_manager_tools_window_controller.cpp
@@ -194,7 +194,7 @@ void WindowManagerToolsWindowController::on_animation(
{ spec.top_left().value().x.as_int(), spec.top_left().value().y.as_int() },
{ scale.x, scale.y });
- if (container->get_type() == ContainerType::tiled)
+ if (container->get_type() == ContainerType::leaf)
clip(window, new_rectangle);
else
noclip(window);
diff --git a/src/workspace.cpp b/src/workspace.cpp
index 9961251..be1cc6e 100644
--- a/src/workspace.cpp
+++ b/src/workspace.cpp
@@ -24,6 +24,7 @@ along with this program. If not, see .
#include "output.h"
#include "tiling_window_tree.h"
#include "window_helpers.h"
+#include "parent_container.h"
#include "floating_container.h"
#include "shell_component_container.h"
@@ -73,7 +74,7 @@ Workspace::Workspace(
std::shared_ptr const& config,
WindowController& window_controller,
CompositorState const& state,
- miral::MinimalWindowManager& floating_window_manager) :
+ std::shared_ptr const& floating_window_manager) :
output { output },
tools { tools },
workspace { workspace },
@@ -113,14 +114,14 @@ ContainerType Workspace::allocate_position(
: hint;
switch (layout)
{
- case ContainerType::tiled:
+ case ContainerType::leaf:
{
requested_specification = tree->place_new_window(requested_specification, get_layout_container());
- return ContainerType::tiled;
+ return ContainerType::leaf;
}
case ContainerType::floating:
{
- requested_specification = floating_window_manager.place_new_window(app_info, requested_specification);
+ requested_specification = floating_window_manager->place_new_window(app_info, requested_specification);
requested_specification.server_side_decorated() = false;
return ContainerType::floating;
}
@@ -129,20 +130,20 @@ ContainerType Workspace::allocate_position(
}
}
-std::shared_ptr Workspace::advise_new_window(
+std::shared_ptr Workspace::create_container(
miral::WindowInfo const& window_info, ContainerType type)
{
std::shared_ptr container = nullptr;
switch (type)
{
- case ContainerType::tiled:
+ case ContainerType::leaf:
{
container = tree->confirm_window(window_info, get_layout_container());
break;
}
case ContainerType::floating:
{
- floating_window_manager.advise_new_window(window_info);
+ floating_window_manager->advise_new_window(window_info);
container = add_floating_window(window_info.window());
break;
}
@@ -167,7 +168,7 @@ std::shared_ptr Workspace::advise_new_window(
// TODO: hack
// Warning: We need to advise fullscreen only after we've associated the userdata() appropriately
- if (type == ContainerType::tiled && window_helpers::is_window_fullscreen(window_info.state()))
+ if (type == ContainerType::leaf && window_helpers::is_window_fullscreen(window_info.state()))
{
tree->advise_fullscreen_container(*Container::as_leaf(container));
}
@@ -183,23 +184,24 @@ void Workspace::handle_ready_hack(LeafContainer& container)
window_controller.raise(window->window().value());
if (tree->has_fullscreen_window())
- window_controller.raise(state.active_window);
+ window_controller.raise(state.active->window().value());
}
-void Workspace::advise_delete_window(std::shared_ptr const& container)
+void Workspace::delete_container(std::shared_ptr const &container)
{
switch (container->get_type())
{
- case ContainerType::tiled:
+ case ContainerType::leaf:
{
tree->advise_delete_window(container);
break;
}
case ContainerType::floating:
{
- auto window = Container::as_floating(container)->window().value();
- floating_window_manager.advise_delete_window(window_controller.info_for(window));
- remove_floating_window(window);
+ auto floating = Container::as_floating(container);
+ floating_window_manager->advise_delete_window(window_controller.info_for(floating->window().value()));
+ floating_windows.erase(
+ std::remove(floating_windows.begin(), floating_windows.end(), floating), floating_windows.end());
break;
}
default:
@@ -273,7 +275,7 @@ bool Workspace::select_window_from_point(int x, int y)
{
auto window = floating->window().value();
geom::Rectangle window_area(window.top_left(), window.size());
- if (window == state.active_window && window_area.contains(geom::Point(x, y)))
+ if (floating == state.active && window_area.contains(geom::Point(x, y)))
return false;
else if (window_area.contains(geom::Point(x, y)))
{
@@ -283,7 +285,7 @@ bool Workspace::select_window_from_point(int x, int y)
}
auto node = tree->select_window_from_point(x, y);
- if (node && node->window().value() != state.active_window)
+ if (node && node != state.active)
{
window_controller.select_active_window(node->window().value());
return true;
@@ -301,7 +303,7 @@ void Workspace::toggle_floating(std::shared_ptr const& container)
switch (container->get_type())
{
- case ContainerType::tiled:
+ case ContainerType::leaf:
{
if (tree->has_fullscreen_window())
{
@@ -310,14 +312,14 @@ void Workspace::toggle_floating(std::shared_ptr const& container)
}
// First, remove the window from the tiling window tree
- advise_delete_window(window_controller.get_container(*window));
+ delete_container(window_controller.get_container(*window));
// Next, ask the floating window manager to place the new window
auto& prev_info = window_controller.info_for(*window);
auto spec = window_helpers::copy_from(prev_info);
spec.top_left() = geom::Point { window->top_left().x.as_int() + 20, window->top_left().y.as_int() + 20 };
window_controller.noclip(*window);
- auto new_spec = floating_window_manager.place_new_window(
+ auto new_spec = floating_window_manager->place_new_window(
tools.info_for(window->application()),
spec);
tools.modify_window(*window, new_spec);
@@ -328,7 +330,7 @@ void Workspace::toggle_floating(std::shared_ptr const& container)
case ContainerType::floating:
{
// First, remove the floating window
- advise_delete_window(window_controller.get_container(*window));
+ delete_container(window_controller.get_container(*window));
// Next, ask the tiling tree to place the new window
auto& prev_info = window_controller.info_for(*window);
@@ -336,7 +338,7 @@ void Workspace::toggle_floating(std::shared_ptr const& container)
auto new_spec = tree->place_new_window(spec, nullptr);
tools.modify_window(*window, new_spec);
- new_type = ContainerType::tiled;
+ new_type = ContainerType::leaf;
break;
}
default:
@@ -346,9 +348,9 @@ void Workspace::toggle_floating(std::shared_ptr const& container)
// In all cases, advise a new window and pretend like it is ready again
auto& info = window_controller.info_for(*window);
- auto new_container = advise_new_window(info, new_type);
+ auto new_container = create_container(info, new_type);
new_container->handle_ready();
- window_controller.select_active_window(state.active_window);
+ window_controller.select_active_window(state.active->window().value());
}
void Workspace::hide()
@@ -396,11 +398,11 @@ void Workspace::transfer_pinned_windows_to(std::shared_ptr const& oth
}
}
-bool Workspace::has_floating_window(miral::Window const& window)
+bool Workspace::has_floating_window(std::shared_ptr const& container)
{
for (auto const& other : floating_windows)
{
- if (other->window() == window)
+ if (other == container)
return true;
}
@@ -415,14 +417,6 @@ std::shared_ptr Workspace::add_floating_window(miral::Window
return floating;
}
-void Workspace::remove_floating_window(miral::Window const& window)
-{
- floating_windows.erase(std::remove_if(floating_windows.begin(), floating_windows.end(), [&window](std::shared_ptr const& floating)
- {
- return floating->window() == window;
- }));
-}
-
Output* Workspace::get_output()
{
return output;
@@ -448,6 +442,29 @@ bool Workspace::is_empty() const
return tree->is_empty() && floating_windows.empty();
}
+void Workspace::graft(std::shared_ptr const& container)
+{
+ switch (container->get_type())
+ {
+ case ContainerType::floating:
+ {
+ auto floating = Container::as_floating(container);
+ floating->set_workspace(this);
+ floating_windows.push_back(floating);
+ break;
+ }
+ case ContainerType::parent:
+ tree->graft(Container::as_parent(container));
+ break;
+ case ContainerType::leaf:
+ tree->graft(Container::as_leaf(container));
+ break;
+ default:
+ mir::log_error("Workspace::graft: ungraftable container type: %d", (int)container->get_type());
+ break;
+ }
+}
+
int Workspace::workspace_to_number(int workspace)
{
if (workspace == 0)
@@ -458,16 +475,15 @@ int Workspace::workspace_to_number(int workspace)
std::shared_ptr Workspace::get_layout_container()
{
- if (!state.active_window)
+ if (!state.active)
return nullptr;
- auto container = window_controller.get_container(state.active_window);
- if (!container)
- return nullptr;
-
- auto parent = container->get_parent().lock();
+ auto parent = state.active->get_parent().lock();
if (!parent)
return nullptr;
+ if (parent->get_workspace() != this)
+ return nullptr;
+
return parent;
}
\ No newline at end of file
diff --git a/src/workspace.h b/src/workspace.h
index fd6787d..65253b9 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -47,7 +47,7 @@ public:
std::shared_ptr const& config,
WindowController& window_controller,
CompositorState const& state,
- miral::MinimalWindowManager& floating_window_manager);
+ std::shared_ptr const& floating_window_manager);
[[nodiscard]] int get_workspace() const;
void set_area(mir::geometry::Rectangle const&);
@@ -57,22 +57,22 @@ public:
miral::ApplicationInfo const& app_info,
miral::WindowSpecification& requested_specification,
ContainerType hint);
- std::shared_ptr advise_new_window(
+ std::shared_ptr create_container(
miral::WindowInfo const& window_info, ContainerType type);
void handle_ready_hack(LeafContainer& container);
- void advise_delete_window(const std::shared_ptr& container);
+ void delete_container(std::shared_ptr const &container);
void show();
void hide();
void transfer_pinned_windows_to(std::shared_ptr const& other);
void for_each_window(std::function)> const&);
bool select_window_from_point(int x, int y);
void toggle_floating(std::shared_ptr const&);
- bool has_floating_window(miral::Window const&);
+ bool has_floating_window(std::shared_ptr const&);
std::shared_ptr add_floating_window(miral::Window const&);
- void remove_floating_window(miral::Window const&);
Output* get_output();
void trigger_rerender();
[[nodiscard]] bool is_empty() const;
+ void graft(std::shared_ptr const&);
static int workspace_to_number(int workspace);
private:
@@ -84,7 +84,7 @@ private:
WindowController& window_controller;
CompositorState const& state;
std::shared_ptr config;
- miral::MinimalWindowManager& floating_window_manager;
+ std::shared_ptr floating_window_manager;
/// Retrieves the container that is currently being used for layout
std::shared_ptr get_layout_container();
diff --git a/tests/tiling_window_tree_test.cpp b/tests/tiling_window_tree_test.cpp
index 4a822bd..fb1a2df 100644
--- a/tests/tiling_window_tree_test.cpp
+++ b/tests/tiling_window_tree_test.cpp
@@ -125,7 +125,7 @@ public:
auto leaf = tree.confirm_window(info, nullptr);
pairs.push_back({ window, leaf });
- state.active_window = window;
+ state.active = leaf;
tree.advise_focus_gained(*leaf);
return leaf;
}